Django reverse query by the last created object

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-06 13:13:45
iMom0

This solution is a little twisted, but I think it will work:

from django.db.models import Max

max_status_ids = SomeActivity.objects.filter(statuses__isnull=False).annotate(
              last_status_id=Max('statuses__id')
              ).values_list('last_status_id', flat=True)
status_satisfied_ids = SomeStatus.objects.filter(id__in=list(max_status_ids),
              status__in=[1, 2]).values_list('id', flat=True)
activities = SomeActivity.objects.filter(statuses__id__in=list(
              status_satisfied_ids))

I hope there is a better solution.


update

Try

max_status_ids = SomeActivity.objects.annotate(last_status_id=Max('statuses')
                                    ).values('last_status_id')
activities = SomeActivity.objects.filter(statuses__in=max_status_ids,
                                         statuses__status__in=(1,2))
  1. Django automatically generates sub-query when qs, qs.values() or qs.values_list() is used after __in lookup. Thus there is no need to wrap the querysets w/ list() (which also introduces unnecessary evaluation and thus unnecessary intermediate SQLs) or to write flat=True inside qs.values_list()
  2. statuses__id__in lookup inside activities already introduces a table join, thus it's bette to move status__in from status_satisfied_ids into activities to take advantage of the join. Or else, status_satisfied_ids would introduce extra select.

Or you could use Window functions of PostgreSQL to filter by ranked position directly.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!