【问题标题】:Django queryset annotate field to be a list/querysetDjango queryset 将字段注释为列表/查询集
【发布时间】:2017-08-29 09:42:59
【问题描述】:

我正在尝试使用 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。我知道这种语法是错误的。感谢您的帮助。

【问题讨论】:

  • 您使用的是哪个数据库?
  • 我正在使用 psql

标签: python django django-queryset django-annotate


【解决方案1】:

如果您使用 postgresqldjango >= 1.9,您可以使用 postgres 特定的聚合函数,例如 ArrayAgg:

返回连接成数组的值列表,包括空值。

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

【讨论】:

  • 你能算出聚合中的条件表达式吗?我想知道怎么做。
  • 在下面查看我的评论
  • 我明白我错过了什么。我使用的是then=F("related_model__pk"),这就是它不起作用的原因。谢谢。
  • 我怎样才能让它成为一组值呢?
【解决方案2】:

我做过类似的事情:

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_c 下都有 Nonepk 的列表。您还可以为Case 定义其他默认值,而不是None

【讨论】:

  • 是否可以从数组字段中过滤掉None项?
  • 我已经使用 python filter 函数在应用程序中过滤掉了它们。我不确定是否可以在数据库级别。
  • field_a=ArrayAgg("related_model__pk", filter=Q(related_model__field="A")) 有点干净。但是,我不确定在发布此答案时ArrayAgg 是否支持filter
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-17
  • 1970-01-01
  • 2019-08-03
  • 2020-06-13
  • 1970-01-01
  • 2020-07-31
  • 2018-02-06
相关资源
最近更新 更多