Django annotate возвращает дублирующиеся записи

Я аннотирую набор запросов следующим образом:

class ItemQuerySet(models.QuerySet):
    def annotate_subitem_stats(self):
        return self.annotate(
            count_subitems=Count('subitems'),
            has_sent_subitems=Case(
                When(subitems__status=Status.sent, then=Value(True)),
                default=Value(False)
            ),
        )

В данном примере SubItem является моделью с внешним ключом к Item.

При выполнении этого кода происходит странное поведение. Предположим, у нас есть 1 Item и 2 SubItem, связанных с ним. У одного подпункта статус отправлен, а у другого - нет. Когда я запускаю annotate на queryset, queryset возвращает элемент дважды, один раз с has_sent_subitems, установленным в True, а другой - в False. Другая странная вещь заключается в том, что один дубликат имеет count_subitems == 1, а другой count_subitems == 1, как будто queryset разделил элемент на две строки, одна из которых status == 'sent', а другая status != 'sent'.

Вот как выглядит аннотированный набор запросов:

[
    {
        'name': 'Item Name',
        'count_subitems': 1,
        'has_sent_subitem': False
    },
    {
        'name': 'Item Name',
        'count_subitems': 1,
        'has_sent_subitem': True
    }
]

Вот как выглядит база данных, используя псевдокод:

item = Item()
SubItem(item=item, status=draft)
SubItem(item=item, status=sent)

Я почти уверен, что это связано со строкой When(subitems__status=Status.sent, then=Value(True)),. Есть ли способ сделать так, чтобы эта строка проверяла, что только 1 элемент имеет статус отправлен, а затем устанавливала аннотацию в true и двигалась дальше?

P.S. Использование .distinct() не сработало. Я не могу использовать .distinct(field), потому что annotate() + distinct(fields) is not implemented.

Вы можете использовать для этого подзапрос Exists, чтобы избежать объединения, вызванного subitems__status, так:

from django.db.models import Exists, OuterRef


class ItemQuerySet(models.QuerySet):
    def annotate_subitem_stats(self):
        return self.annotate(
            count_subitems=Count('subitems'),
            has_sent_subitems=Exists(
                SubItem.objects.filter(item=OuterRef('pk'), status=Status.sent)
            ),
        )
Вернуться на верх