Python Django按上次创建的对象进行反向查询

Python Django按上次创建的对象进行反向查询,python,django,postgresql,django-queryset,Python,Django,Postgresql,Django Queryset,我有两种型号: 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.Fo

我有两种型号:

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

但问题是,当我想进行一个查询,返回所有具有上次状态匹配状态的活动时,=[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))
我希望有更好的解决办法

更新

试一试

当在查找中的u之后使用qs、qs.values或qs.values_列表时,Django会自动生成子查询。因此,不需要包装querysets w/list,因为它也引入了不必要的求值和不必要的中间SQL,或者在qs.values\u列表中写入flat=True 活动内部查找中的status\uu id\uu已经引入了一个表联接,因此最好将status\uu in从status\u successed\u id移动到活动中,以利用联接。否则,状态满足ID将引入额外的选择。
或者您可以使用直接按排名位置进行筛选。

SomeStatus对象的列表[1,2]?状态。我对问题进行了编辑以使其更加清晰。@okm我阅读了1.4版的文档,本节末尾,django建议使用mysql拆分查询,我不知道在pg中会更好。我不知道mysql将达到什么性能级别,他们说这很糟糕。通常情况下,博士后在这类工作中工作得很好——因为没有那么大的桌子。对于大型表,in子查询仍然比or窗口函数慢。第二,大in子句的性能不好,无论是Postgres还是Postgres都不好。只需在Postgres中进行测试,两个表有100k行in'子句最慢:整个=>3200ms,极限10=>800ms,偏移50000,极限10=>2950ms;自连接:整个=>650ms,限制10=>0.3ms,偏移50000限制10=>620ms;窗口功能:整个=>510ms,限制10=>310ms,偏移50000限制10=>440ms。对于大型表,我们看不到上述方法的实时性能都很好,如果操作频繁,我们应该添加缓存或非规范化字段。
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))