Как получить объединенный последний объект в django ORM?

У меня есть две таблицы 1:N, связанные между собой.

Я хочу получить только одну модель последней сделки для каждой модели real_estate.

Я присоединился к prefetch_related и результатом list(real_estates)[0].latest_deals является [].

            latest_deals = (
                deal_q.filter(real_estate_id=OuterRef("id"))
                .order_by("-deal_year", "-deal_month", "-deal_day")
                .values("id")[:1]
            )

            real_estates = (
                RealEstate.objects.prefetch_related(
                    Prefetch(
                        lookup="deals",
                        queryset=deal_q.filter(id__in=Subquery(latest_deals)),
                        to_attr="latest_deals",
                    )
                )
                .filter(
                    deals__is_deal_canceled=False,
                    latitude__gte=dto.sw_lat,
                    latitude__lte=dto.ne_lat,
                    longitude__gte=dto.sw_lng,
                    longitude__lte=dto.ne_lng,
                )
                .distinct()
            )

            list(real_estates)[0].latest_deals

В чем проблема такого подхода?

Вероятно, вы даже можете сделать это в том же запросе с помощью FilteredRelation [Django-doc]:

from django.db.models import FilteredRelation, OuterRef, Q, Subquery

qs = RealEstate.objects.annotate(
    latest_deal=FilteredRelation(
        'deals',
        condition=Q(
            post=Subquery(
                Deal.objects.filter(real_estate=OuterRef('pk'))
                .order_by('-deal_year', '-deal_month', '-deal_day')
                .values('pk')[:1]
            ),
        ),
    ),
).select_related('latest_deal')

Тогда для каждого RealEstate будет получена последняя Deal.


Note: Please don't specify a year, month and day field: use a DateField [Django-doc]: this makes sure that the month is in range, and the day is in range of the number of that month in that year. It also will be stored more compactly in the database, and ordering will be done more efficiently.

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