Django ORM - 获取组的最新记录

时间:2021-01-06 13:21:44

Imagine we have the Django ORM model Meetup with the following definition:

想象一下,我们有Django ORM模型Meetup,其定义如下:

class Meetup(models.Model):
    language = models.CharField()
    date = models.DateField(auto_now=True)

I'd like to fetch the latest meetup for each language.

我想为每种语言取一个最新的聚会。

It would seem you could use Django Aggregates to make this lookup easy:

看起来你可以使用Django Aggregates来简化这个查找:

Meetup.objects.annotate(latest_date=Max("date")).values("language", "latest_date")

In my mind this should fetch the "latest" meetup for each language. But that's not the case:

在我看来,这应该取得每种语言的“最新”聚会。但事实并非如此:

>>> Meetup.objects.create(language='python')
<Meetup: Meetup object>
>>> Meetup.objects.create(language='python')
<Meetup: Meetup object>
>>> Meetup.objects.create(language='node')
<Meetup: Meetup object>
>>> Meetup.objects.create(language='node')
<Meetup: Meetup object>
>>> Meetup.objects.annotate(latest_date=Max("date")).values("language", "latest_date").count()
4

I expected to get just the two latest Python and Node meetups!

我期望得到两个最新的Python和Node聚会!

How can I construct a query that will fetch only the latest meetups for each language?

如何构建一个只能获取每种语言的最新聚会的查询?

PS. I'm using MySQL as my backend.

PS。我使用MySQL作为我的后端。

1 个解决方案

#1


10  

Put your values clause before the annotate.

将您的values子句放在注释之前。

From the aggregation docs:

来自聚合文档:

If the values() clause precedes the annotate(), the annotation will be computed using the grouping described by the values() clause.

如果values()子句在annotate()之前,则将使用values()子句描述的分组计算注释。

However, if the annotate() clause precedes the values() clause, the annotations will be generated over the entire query set. In this case, the values() clause only constrains the fields that are generated on output.

但是,如果annotate()子句位于values()子句之前,则将在整个查询集上生成注释。在这种情况下,values()子句仅约束输出时生成的字段。

So this should do it:

所以这应该这样做:

Meetup.objects.values('language').annotate(latest_date=Max('date'))

#1


10  

Put your values clause before the annotate.

将您的values子句放在注释之前。

From the aggregation docs:

来自聚合文档:

If the values() clause precedes the annotate(), the annotation will be computed using the grouping described by the values() clause.

如果values()子句在annotate()之前,则将使用values()子句描述的分组计算注释。

However, if the annotate() clause precedes the values() clause, the annotations will be generated over the entire query set. In this case, the values() clause only constrains the fields that are generated on output.

但是,如果annotate()子句位于values()子句之前,则将在整个查询集上生成注释。在这种情况下,values()子句仅约束输出时生成的字段。

So this should do it:

所以这应该这样做:

Meetup.objects.values('language').annotate(latest_date=Max('date'))