Django 反向查询最后创建的对象

Posted

技术标签:

【中文标题】Django 反向查询最后创建的对象【英文标题】:Django reverse query by the last created object 【发布时间】:2013-02-02 01:39:59 【问题描述】:

我有两个模型:

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

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

【问题讨论】:

列表[1,2]是什么? 来自 SomeStatus 对象的状态。我将问题编辑得更清楚。 【参考方案1】:

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

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

或者您可以使用Window functions of PostgreSQL 直接按排名进行过滤。

【讨论】:

@okm 看了 1.4 的 doc,docs.djangoproject.com/en/1.4/ref/models/querysets/#in 本节结束,django 建议使用 mysql 拆分查询,不知道在 pg 中会不会更好。 我不知道 MySQL 会达到什么水平的性能,他们说这很糟糕。通常 Postgres 在这种工作上工作得很好——对于不是那么大的表。对于大表,in 子查询仍然比self-join 或窗口函数慢。其次,大的in 子句表现不佳,in MySQL 或 Postgres 都没有。 只需在 Postgres 中使用两个具有 100k 行的表进行测试。 'in' 子句最慢:整个 => 3200ms,limit 10 => 800ms,offset 50000 limit 10 => 2950ms;自加入:整体 => 650ms,限制 10 => 0.3ms,偏移量 50000 限制 10 => 620ms;窗口函数:整体 => 510ms,限制 10 => 310ms,偏移 50000 限制 10 => 440ms。我们可以看到上述方法对于大表的实时性能都不是很好,如果操作频繁,我们应该添加缓存或反规范化字段。

以上是关于Django 反向查询最后创建的对象的主要内容,如果未能解决你的问题,请参考以下文章

如何通过django中的多级反向外键获取相关对象查询集?

编写一个 django 查询并在一次数据库中获取反向相关对象!

django中Model表的反向查询

django2.0+反向查询抛异常处理

Django总结(待续)

包含列表中所有值的 Django 反向查询集