2
class Language(models.Model):
    iso_code = models.CharField()

class Publisher(models.Model)
    name = models.CharField()

class Book(modle.Model):
    name = models.CharField()
    language = models.ForeignKey(Language)
    publisher = models.ForeignKey(Publisher, related_name='books')

lang_ids = [1,2]

qs = Publisher.objects.annotate(
    x=ArrayAgg(
        Case(
            When(
                books__language__in=lang_ids,
                then="books__name"
            )
        )
    )
)

我想过滤 qs,如下所示 - https://docs.djangoproject.com/en/3.1/ref/contrib/postgres/fields/#len

qs.filter(x__len=2)

为什么不能以这种方式过滤 qs?我收到一个错误 IndexError: tuple index out of range。

ArrayAgg 中的输出字段是 ArrayField

class ArrayAgg(OrderableAggMixin, Aggregate):
    function = 'ARRAY_AGG'
    template = '%(function)s(%(distinct)s%(expressions)s %(ordering)s)'
    allow_distinct = True

    @property
    def output_field(self):
        return ArrayField(self.source_expressions[0].output_field)

    def convert_value(self, value, expression, connection):
        if not value:
            return []
        return value
4

1 回答 1

2

为了获得 ArrayField 的长度,您将需要使用不同的函数,还有cardinalityarray_length。更多信息在这里https://www.postgresql.org/docs/current/functions-array.html

如果您只有一个维度数组,您可以使用cardinality

from django.db import models

class ArrayLength(models.Func):
    function = 'CARDINALITY'


qs = Publisher.objects.annotate(
    x=ArrayAgg(
        Case(
            When(
                books__language__in=lang_ids,
                then="books__name"
            )
        )
    )
)
qs = qs.annotate(x_len=ArrayLength('x')) # notice `x_len` is just a name, you can use anything
qs = qs.filter(x_len=2)  # the actual filter

于 2021-11-06T07:46:25.503 回答