【问题标题】:Django annotate with model valuesDjango 使用模型值进行注释
【发布时间】:2021-10-15 11:02:21
【问题描述】:

Django docs on aggregation 给出以下注释示例:

for store in Store.objects.all():
    store.min_price # Error! min_price not defined!
for store in Store.objects.annotate(min_price=Min('books__price')):
    store.min_price # Fine

但是,我们只注释了一个字段。我们只知道最便宜的书价格是多少,但不知道哪本书是最便宜的。如果我希望注释的结果恰好是那本书,而不仅仅是它的价格呢? (我会调用这个函数或类AggregateRelation

for store in Store.objects.annotate(
   cheapest_book=AggregateRelation('books__price', Min)
):
    store.cheapest_book.price
    store.cheapest_book.title

有没有办法做到这一点?

我检查了FilteredRelation,但这仅对过滤有用。它不会真正检索实例。

【问题讨论】:

  • 好吧,如果 SQL 中有方法,您可以运行原始 SQL 查询。我知道这可能不是您想要的。

标签: sql django annotations


【解决方案1】:

如果(且仅当)您使用的是 PostgreSQL,那么我认为使用 .distinct(fields) 可以得到答案

Book.objects.order_by('store_id', 'price').distinct('store_id')

如果我正确理解了文档(上面链接),应该为您提供每家商店最便宜的书。添加select_related()应该意味着你在引用book.store.whatever时不会再次打DB

如果您没有 PostgreSQL,我认为您可以使用 SubQuery。以下是我尝试遵循的文档:

from django.db.models import OuterRef, Subquery

cheapest = Book.objects.filter(store=OuterRef('pk')).order_by('price')
stores = Store.objects.annotate(cheapest_book_pk=Subquery(cheapest.values('pk')[:1]))

这样的东西会给你一个 Store 对象的列表,每个对象都用它正在销售的最便宜的书的 pk 进行注释。

请告诉我这是否正确!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-05
    • 2013-02-25
    • 2015-09-22
    • 1970-01-01
    • 2019-12-30
    • 2019-01-13
    • 2018-02-24
    相关资源
    最近更新 更多