Django queryset注释字段为列表/查询集

23

我正在尝试使用Django的注释功能来创建查询集字段,该字段是某个相关模型属性值列表。

queryset = ...
qs = queryset.annotate(
    list_field=SomeAggregateFunction(
        Case(When(related_model__field="abc"), then="related_model__id")
    ),
    list_elements=Count(F('list_field'))
)

我在考虑用某个分隔符连接所有这些id,但我不知道适当的函数。另一个解决方案是将list_field作为queryset。我知道这种语法是错误的。感谢任何帮助。


你使用哪个数据库? - AKS
我正在使用psql。 - zyks
2个回答

23
如果你正在使用 postgresqldjango >= 1.9,你可以使用Postgres特有的聚合函数,例如 ArrayAgg:

返回一个包括 null 值在内的值列表,连接成一个数组。

如果你需要使用分隔符连接这些值,你也可以使用 StringAgg

你能解决聚合内的条件表达式吗?我想知道怎么做。 - AKS
请看我下面的评论。 - zyks
我明白我错在哪里了。我使用的是 then=F("related_model__pk"),这就是为什么它没有起作用的原因。谢谢。 - AKS
怎么将它变成一组值的集合呢? - ThunderHorn

9
我曾经做过这样的事情:
qs = queryset \
    .annotate(
        field_a=ArrayAgg(Case(When(
            related_model__field="A",
            then="related_model__pk")
        )),
        field_b=ArrayAgg(Case(When(
            related_model__field="B",
            then="related_model__pk")
        )),
        field_c=ArrayAgg(Case(When(
            related_model__field="C",
            then="related_model__pk")
        ))
    )

现在,每个查询集中的对象下面都有 field_afield_bfield_cNonepk 列表。您还可以定义其他默认值来代替 None 作为 Case 的值。请注意,保留了 HTML 标签。

2
能否从数组字段中过滤掉 None 项? - Joseph M
我已经使用Python的filter函数在应用程序中对它们进行了过滤。我不确定是否可以在数据库层面上实现这一点。 - zyks
4
field_a=ArrayAgg("related_model__pk", filter=Q(related_model__field="A")) 这个写法更简洁。但是,我不确定在这篇答案发布时 ArrayAgg 是否支持 filter - Dušan Maďar
刚刚在这篇文章中发现了ArrayAgg,真是太棒了。我需要注释相关对象的计数,同时也要获取它们的ID列表。ArrayAgg救了我一命。 - Milo Persic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接