Django queryset用于获取每个唯一属性值的最新信息

时间:2011-04-16 20:47:00

标签: django django-queryset

class SwallowMigration(models.Model):
    swallow = models.ForeignKey(Swallow)
    date = models.DateTimeField(auto_now_add=True)
    coconuts_carried = models.IntegerField()

如何获得每次燕子的最新迁移?

当然.latest()只给了我最新的条目。有没有办法(可能使用Max with Max?)来获取另一个字段中某个值的每个实例的最新信息?

2 个答案:

答案 0 :(得分:3)

如果仅使用Swallow实例并且最近迁移的日期已足够,则以下内容应该为您执行此操作:

Swallow.objects.annotate(latest_migration=Max('swallowmigration__date'))

生成的查询集中的每个Swallow实例都将具有“latest_migration”属性,该属性是相关对象的最大日期时间。

如果确实需要SwallowMigration实例,则会花费N + 1个查询,其中N是Swallow实例的数量。像下面这样的东西会为你做这件事,虽然你会有SwallowMigration对象,每个对象都有一个预取的Swallow实例,而不是相反。处理列表并反转它们并不困难,将SwallowMigration实例设置为Swallow实例的属性。

qs = SwallowMigration.objects.values(
    'swallow_id'
).annotate(
    latest_migration=Max('date')
)
migrations = []
for vals in qs:
    sm = SwallowMigration.objects.select_related(
        'swallow'
    ).get(
        swallow=vals['swallow_id'],
        date=vals['date'],
    )
    migrations.append(sm)

可能(可能)是一种在单个查询中返回所需数据的方法,但它必须是原始SQL,您必须使用原样的数据或构建模型来自它的实例。

如果要经常执行此代码,将Swallow上的外键添加到最新的SwallowMigration可能是值得的,这样您就可以使用select_related()在单个查询中轻松检索它们。您必须确保在添加新的SwallowMigration实例时更新该外键。

答案 1 :(得分:-2)

我想你可以像这样使用Max:

Swallow.objects.annotate(last_migration_id=Max('swallowmigration__pk'))

但我不确定它对你有什么好处,因为你必须通过id获取所有迁移,然后将它们附加到Swallow。