Множественные поля аннотаций 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() даст неверные результаты, поскольку вместо подзапросов используются объединения
Например, если к посту оставлено 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
будут зависеть от ваших моделей, конечно.