Django 查询集获取每个唯一属性值的最新值

发布于 2024-11-01 19:30:05 字数 297 浏览 1 评论 0原文

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

如何获取每只燕子的最新迁徙信息?

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

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

How can I get the latest migration for each swallow?

Of course .latest() only gives me the very most recent entry. Is there a way (maybe using Aggregation with Max?) to get the latest for each instance of some value in another field?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

满意归宿 2024-11-08 19:30:05

如果仅拥有 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_lated() 在单个查询中轻松检索它们。您只需确保在添加新的 SwallowMigration 实例时保持外键更新即可。

If just having the Swallow instance and only the date of the most recent migration is enough, the following should do that for you:

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

Each Swallow instance from the resulting queryset will have a "latest_migration" attribute which would be the maximum datetime from the related objects.

If you do need the SwallowMigration instance, it is going to cost you N+1 queries, where N is the number of Swallow instances. Something like the following would do that for you, though you would have SwallowMigration objects with a prefetched Swallow instance on each instead of the other way around. It wouldn't be difficult to process the list and reverse them, setting the SwallowMigration instance as an attribute of the Swallow instance.

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)

There may be (probably is) a way to return all of the data you want in a single query, but it would have to be raw SQL and you'd have to either use the data from that as is or construct model instances from it.

If this code is going to be executed frequently, it might be worth it to add a foreign key on Swallow to the latest SwallowMigration so that you can easily retrieve them in a single query using select_related(). You'd just have to make sure to keep that foreign key updated as new SwallowMigration instances are added.

只是偏爱你 2024-11-08 19:30:05

嗯,我认为你可以像这样使用 Max:

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

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

Hm i think you can use Max like this:

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

But i'm not sure what good would it make for you, since you'll have to fetch all migrations by id and then attach them to Swallow anyway.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文