【问题标题】:Django Aggregate on related field with filterDjango 使用过滤器聚合相关字段
【发布时间】:2020-01-30 13:58:09
【问题描述】:

以下问题:
我有包含产品的产品组。这些产品可以在前端可见或不可见。我使用frontend()(包含过滤器)方法确定它们的可见性,如下所示:

product_groups.first().products.frontend()

现在我想确定是否仅在主页中有四个或更多产品时才在主页上放置产品组的链接。
使用注释我会这样做:

product_groups.annotate(num_products=Count('products')).filter(num_products__gte=4)

但这给了我所有产品的数量,而不是前端可见产品的数量。

那么如何将附加过滤器frontend() 放入我的查询中?需要明确的是,我希望 Count() 不是在 'products' 上,而是在 products.frontend() 上。

编辑:
这不是建议问题的重复。如果过滤器函数frontend() 足够简单,可以将过滤器拉出并粘贴到聚合函数中,那么建议的问题将回答我的问题。

我的frontend() 函数相当复杂,是多个其他过滤器函数的集合。所以我真的很想使用frontend()函数。

编辑:
这需要在 Django 1.8 中工作。

【问题讨论】:

  • frontend() 中的任何过滤器都可以应用于CountCount(products, filter=Q(...))
  • @dirkgroten 这就是我的想法。但是我不能直接使用frontend()?我在frontend() 中获得的过滤器非常复杂,并且本身就是其他功能的集合。

标签: django filter annotations


【解决方案1】:

如果您想在您的Product 模型的Queryset 上重用frontend() 方法,那么您可以使用Subquery aggregate expressions

# assumption: `Product` has a fk to `ProductGroup`
# assumption 2: frontend() returns a `Queryset` of `Product` and is a method of `Product` model's default `Queryset`
frontend_products = Product.objects.filter(product_group=OuterRef('pk')).frontend().values('product_group')
total_products = frontend_products.annotate(total=Count('pk')).values('total')
q = product_groups.annotate(num_frontend_products=Subquery(total_products, output_field=IntegerField()))

请注意,对于没有任何对应产品的组,这将使用None 填充num_frontend_products 而不是0。您可能希望使用条件注释进一步修改查询集,以将 None 替换为 0。

【讨论】:

  • 让我猜猜。在 Django 1.8 中没有办法做到这一点?
  • 这就是我害怕的。所以我只能手动执行此操作。非常感谢您的努力。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多