2

我有两个模型:

class SomeActivity(models.Model):
    name = models.ChartField(max_length=100)

class SomeStatus(models.Model):
    name = models.CharField(max_length=100)
    status = models.IntegerField(choises=STATUS_CHOISES)
    some_activity = models.ForeignKey(SomeActivity, related_name='statuses')

活动的最后创建状态是当前状态。为了得到它,我使用以下代码:

try:
    last_status = some_activity.statuses.latest('id')
except:
    last_status = None

但问题是当我想进行一个返回所有Activities匹配last_status的查询时status__in=[1, 2]

4

1 回答 1

2

这个解决方案有点扭曲,但我认为它会起作用:

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))

我希望有更好的解决方案。


更新

尝试

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 自动生成子查询时qsqs.values()或查找qs.values_list()后使用__in。因此,无需使用 w/ 包装查询集list()(这也引入了不必要的评估,从而引入了不必要的中间 SQL)或在flat=True内部编写qs.values_list()
  2. statuses__id__in内部查找activities已经引入了表连接,因此最好status__instatus_satisfied_ids进入activities到利用连接。否则,status_satisfied_ids会引入额外的选择。

或者您可以使用PostgreSQL 的 Window 函数直接按排名位置进行过滤。

于 2013-02-17T16:56:57.033 回答