После обновления до Django 3.2 мои аннотации на полях `ArrayAgg` не работают

У меня есть довольно сложный метод модели, который прекрасно работал до обновления до Django 3.2.8. Он выглядит следующим образом:

@classmethod
def get_inbox_for_user(cls, user: User) -> 'models.QuerySet[ShareRequest]':
    user_principals_ids = list(user.principals.values_list('id', flat=True))

    annotated_share_requests = cls._default_manager\
        .annotate(
            registered_staff_ids=ArrayAgg(
                'contact__registered_staffing__staff_user',
                distinct=True,
            )
        )\
        .annotate(
            primary_registered_staff_ids=ArrayAgg(
                'contact__registered_staffing__staff_user',
                filter=models.Q(contact__registered_staffing__is_primary=True),
                distinct=True,
            )
        )

    filtered_shared_requests = annotated_share_requests\
        .filter(
            (models.Q(primary_registered_staff_ids__isnull=True) & models.Q(registered_staff_ids__contains=[user.id]))
            | (models.Q(primary_registered_staff_ids__isnull=True) & models.Q(registered_staff_ids__overlap=user_principals_ids))
            | models.Q(primary_registered_staff_ids__contains=[user.id])
            | models.Q(primary_registered_staff_ids__contained_by=user_principals_ids)
        )

    return filtered_shared_requests

Опустим детали, важной частью являются мои утверждения аннотаций и дальнейшая фильтрация по ним.

Из примера ниже видно, что registered_staff_ids приводит к [None], что выглядит как часть проблемы:

In [39]: annotated_share_requests.first().registered_staff_ids
Out[39]: [None]

Я смог исправить это, предоставив дополнительный фильтр для моего оператора annotate, превратив это выражение в:

annotated_share_requests = cls._default_manager\
    .annotate(
        registered_staff_ids=ArrayAgg(
            'contact__registered_staffing__staff_user',
            filter=models.Q(contact__registered_staffing__staff_user__isnull=False),
            distinct=True,
        )
    )\
    ...

Теперь результат выглядит так:

In [40]: annotated_share_requests.first().registered_staff_ids
Out[40]: []

Однако дальнейшая фильтрация (в частности, поиск __overlap и __contained_by не работает, например:

In [56]: annotated_share_requests.values_list('primary_registered_staff_ids', flat=True)
Out[56]: <QuerySet [[], []]>  # looks great

In [57]: annotated_share_requests.values_list('registered_staff_ids', flat=True)
Out[57]: <QuerySet [[], []]>  # looks great

In [58]: user_principals_ids
Out[58]: []  # looks great

# BUT!

In [59]: annotated_share_requests.filter(registered_staff_ids__overlap=user_principals_ids)
Out [59]: FieldError: Cannot resolve expression type, unknown output_field

# AND SIMILARLY!

In [61]: annotated_share_requests.filter(primary_registered_staff_ids__contained_by=user_principals_ids)
Out [62]: FieldError: Cannot resolve expression type, unknown output_field

Интересно то, что это кажется проблемой только в случае пустого массива с правой стороны сравнения, так что это работает:

In [76]: annotated_share_requests.filter(primary_registered_staff_ids__contained_by=[1])
Out[76]: <QuerySet []>

In [77]: annotated_share_requests.filter(registered_staff_ids__overlap=[1])
Out[77]: <QuerySet []>

Ищет любые указатели.

Вернуться на верх