Множественные поля аннотаций Django

Когда я пытаюсь аннотировать свою модель, я сталкиваюсь с проблемой, что два поля умножают друг друга

def get_queryset(self):
return self.queryset.annotate(
    my_votes=Count("votes", filter=Q(votes=self.request.user), distinct=False)
    vote_count=Count("votes", distinct=False)
    comments_count=Count("comments", distinct=True)
)

Я знаю, что существует проблема с множественными агрегациями

Объединение нескольких агрегаций с помощью annotate() даст неверные результаты, поскольку вместо подзапросов используются объединения

django docomentation

Например, если к посту оставлено 3 комментария, а я проголосовал за пост 4 раза и всего 7 голосов, то счетчик вернется к следующему значению:

my_votes=12 (4 my_votes * 3 комментария)

vote_count=21 (7 голосов * 3 комментария)

comments_count=3

< < <

Если я удалю счетчик комментариев, все будет работать как надо.

Есть ли другой способ добиться этого?

Спасибо за помощь.

Если просто задать distinct=True не получается, то можно использовать подзапросы, как показано в ответе Серафима здесь. Учитывая, что вы упомянули, что Vote и Post являются отношением many-to-many, вы можете переписать, например, my_votes как подзапрос к таблице through, что-то вроде:

def get_queryset(self):
    my_votes_sq = Subquery(
        Vote.posts.through.objects
         .filter(post_id=OuterRef("pk"), user_id=self.request.user.id)
         .order_by()
         .values("post_id")
         .annotate(count=Count("pk"))
         .values("count"), output_field=IntegerField()
    )
    ...
    return self.queryset.annotate(
        my_votes=Coalesce(my_votes_sq, 0),
        ...
    )

Фактические имена полей для posts, post_id, user_id будут зависеть от ваших моделей, конечно.

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