Django: Возвращать id максимального значения при группировке по внешнему ключу

Информация

У меня есть две модели:

class BookingModel(models.Model):

    [..fields..]


class BookingComponentModel(models.Model):
    STATUS_CHOICES = ['In Progress','Completed','Not Started','Incomplete','Filled','Partially Filled','Cancelled']
    STATUS_CHOICES = [(choice,choice) for choice in STATUS_CHOICES]
    COMPONENT_CHOICES = ['Test','Soak']
    COMPONENT_CHOICES = [(choice,choice) for choice in COMPONENT_CHOICES]

    booking = models.ForeignKey(BookingModel, on_delete=models.CASCADE, null=True, blank=True)
    component_type = models.CharField(max_length=20, choices=COMPONENT_CHOICES)
    status = models.CharField(max_length=50, choices=STATUS_CHOICES, default='Not Started')
    order = models.IntegerField(unique=True)

    [..fields..]

Что я хочу

Я хочу получить компонент бронирования для каждого бронирования, которое имеет последнее значение (максимум) по порядку. Он также должен иметь status='In Progress' и component_type='Soak'.

Например, для таблицы:

+----+------------+----------------+-------------+-------+
| id | booking_id | component_type | status      | order |
+----+------------+----------------+-------------+-------+
| 1  | 1          | Test           | Completed   | 1     |
+----+------------+----------------+-------------+-------+
| 2  | 1          | Soak           | Completed   | 2     |
+----+------------+----------------+-------------+-------+
| 3  | 1          | Soak           | In Progress | 3     |
+----+------------+----------------+-------------+-------+
| 4  | 2          | Test           | Completed   | 1     |
+----+------------+----------------+-------------+-------+
| 5  | 2          | Soak           | In Progress | 2     |
+----+------------+----------------+-------------+-------+
| 6  | 3          | Test           | In Progress | 1     |
+----+------------+----------------+-------------+-------+

Ожидаемым результатом будут идентификаторы: 4 & 6

Что я пробовал

Я пробовал следующее:

BookingComponentModel.objects.values('booking').annotate(max_order=Max('order')).order_by('-booking')

Это не включает фильтрацию, но возвращает max_order для каждого бронирования.

Мне нужен id компонента, который имеет это max_order, чтобы поместить это в подзапрос и позволить мне фильтровать другие условия (status, component_type)

Спасибо

Вы можете использовать Subquery выражение [Django-doc] и работать с:

from django.db.models import OuterRef, Subquery

BookingModel.objects.annotate(
    latest_component_id=Subquery(BookingComponentModel.objects.filter(
        booking_id=OuterRef('pk'), status='In Progress', component_type='Soak'
    ).values('pk').order_by('-order')[:1])
)

Объекты BookingModel, возникающие из этого кверисета, будут иметь дополнительный атрибут latest_component_id, который будет содержать первичный ключ последнего BookingComponentModel с как status 'In Progress', так и как component_type 'Soak'.

Вернуться на верх