Django Count() в нескольких аннотациях
Скажем, у меня простая модель форума:
class User(models.Model):
username = models.CharField(max_length=25)
...
class Topic(models.Model):
user = models.ForeignKey(User)
...
class Post(models.Model):
user = models.ForeignKey(User)
...
Теперь скажите, что я хочу посмотреть, сколько тем и сообщений есть у каждого пользователя подмножества пользователей (например, их имя пользователя начинается с "ab" ).
Итак, если я делаю один запрос для каждого сообщения и темы:
User.objects.filter(username_startswith="ab")
.annotate(posts=Count('post'))
.values_list("username","posts")
Yeilds:
[('abe', 5),('abby', 12),...]
и
User.objects.filter(username_startswith="ab")
.annotate(topics=Count('topic'))
.values_list("username","topics")
Урожайность:
[('abe', 2),('abby', 6),...]
HOWEVER, когда я пытаюсь аннотировать оба, чтобы получить один список, я получаю что-то странное:
User.objects.filter(username_startswith="ab")
.annotate(posts=Count('post'))
.annotate(topics=Count('topic'))
.values_list("username","posts", "topics")
Урожайность:
[('abe', 10, 10),('abby', 72, 72),...]
Почему темы и сообщения умножаются вместе? Я ожидал этого:
[('abe', 5, 2),('abby', 12, 6),...]
Каким будет лучший способ получить правильный список?
Ответы
Ответ 1
Я думаю, Count('topics', distinct=True)
должен поступать правильно. Для избежания дубликатов вместо COUNT(topic.id)
используется COUNT(DISTINCT topic.id)
.
User.objects.filter(
username_startswith="ab").annotate(
posts=Count('post', distinct=True)).annotate(
topics=Count('topic', distinct=True)).values_list(
"username","posts", "topics")
Ответ 2
Попробуйте добавить отличный от вашего последнего набора запросов:
User.objects.filter(
username_startswith="ab").annotate(
posts=Count('post')).annotate(
topics=Count('topic')).values_list(
"username","posts", "topics").distinct()
Подробнее см. https://docs.djangoproject.com/en/1.3/ref/models/querysets/#distinct, но в основном вы получаете повторяющиеся строки, потому что аннотации охватывают несколько таблиц.