如何在django中将QuerySet过滤到每个组的最大成员?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在django中将QuerySet过滤到每个组的最大成员?相关的知识,希望对你有一定的参考价值。

模型是这样的:

class Application(models.Model):
    application_id = models.IntegerField()
    version_id = models.IntegerField()
    # some other attributes

其中application_idversion_id一起确定Application条目,因为一个应用程序可能有多个版本,并且具有最大version_id的条目是应用程序的当前版本。

目标是找到所有应用程序的当前版本。 SQL(在mysql中)类似于:

SELECT
  *
FROM application AS app
WHERE version_id = (SELECT max(version_id)
                    FROM application
                    WHERE application_id = app.application_id);

怎么做到这一点?

请注意,这里的对象是过滤QuerySet,而不是仅获取最大的version_id,这将像使用GROUP BY一样简单,或者在django中使用values(),然后是annotate()。我也对当前版本的其他属性感兴趣。

答案

我自己想通了。 OuterRefSubQuery是诀窍,它是Django 1.11中的新功能,正如here所述。

from django.db.models import OuterRef, Subquery, F

def filter_to_current(qs: QuerySet):
    qs = qs.annotate(current=Subquery(qs.filter(application_id=OuterRef('application_id'))
                                          .order_by('-version_id').values('version_id')[:1])) \
            .filter(version_id=F('current'))

以上是关于如何在django中将QuerySet过滤到每个组的最大成员?的主要内容,如果未能解决你的问题,请参考以下文章

在 Django 中过滤 Queryset 并设计正确的 urls.py 和模板

在 Django 中,如何使用动态字段查找过滤 QuerySet?

在django中动态添加参数到queryset过滤器调用[重复]

Django - 如何将 QuerySet 转换为 Q 对象?

Django QuerySet - 如何“禁用”以前的过滤值

如何过滤 Django QuerySet 的相关字段“全部”或“无”