Как я могу использовать annotate () для подсчета подмножества связанных моделей в Django? - PullRequest
4 голосов
/ 29 сентября 2010

Я пытаюсь использовать функцию аннотации в Django, чтобы добавить счетчик связанной модели в набор запросов. Однако мне не нужно полное количество связанных объектов, я хочу только считать активные (т.е. is_active = True). Я не могу понять, как отфильтровать счет.

(упрощенные) соответствующие модели:

class Post(models.Model):
    user = models.ForeignKey(User)
    title = models.CharField(max_length=80)
    body = models.TextField()

class Comment(models.Model):
    user = models.ForeignKey(User)
    post = models.ForeignKey(Post)
    comment_body = models.CharField(max_length=80)
    is_active = models.BooleanField(default=True)

В представлении я пытаюсь аннотировать набор запросов:

queryset=Post.objects.all().annotate(num_comments=Count('comment', distinct=True))

Выше подсчитываются все комментарии, связанные с постом, тогда как я хочу считать только "is_active". Google и документы Django мне здесь не помогают. Кто-нибудь имел и решил эту проблему?

Ответы [ 3 ]

5 голосов
/ 29 сентября 2010

Вам просто нужно отфильтровать is_active перед тем, как делать аннотацию:

Post.objects.filter(comment__is_active=True).annotate(num_comments=Count('comment'))

См. объяснение здесь .

3 голосов
/ 14 июня 2013

Существует два варианта в зависимости от того, какую базу данных вы используете.Если вы используете MySQL , решение простое и элегантное:

Post.objects.annotate(num_comments=Sum('comment.is_active'))

Это работает, потому что в базе данных логические поля являются целыми числами, а True равен 1, False равен 0.

Но это работает ТОЛЬКО в MySQL и ТОЛЬКО для логических полей .Более общий способ выполнения работы, которая работает со всеми базами данных и может выполнять более сложные проверки, заключается в использовании небольшого «вставленного» SQL-кода:

Post.objects.annotate(num_comments=Count('comment',
    field='CASE WHEN myapp_comment.is_active THEN 1 END'))

У меня та же проблема в моем личном блоге,и это было решением.Я пишу блог для этого.http://venelin.sytes.net/blog/django/filtrirane-na-agregirash-count-v-django/. Это на болгарском языке, но мой сайт использует перевод Google.Перевод не очень хороший, но может помочь понять, почему это работает.

2 голосов
/ 30 сентября 2010

Вот так мне и пришлось «аннотировать» количество активных комментариев в моем наборе запросов Post:

Post.objects.extra(select={"num_comments":
     """
     SELECT COUNT(myapp_comment.id) FROM myapp_reply
     WHERE myapp_comment.is_active='1' AND 
     myapp_comment.post_id = myapp_post.id
     """
     },)

Не очень, но это работает.Как я уже упоминал в комментарии выше, для этого было невозможно использовать встроенную функцию агрегирования annotate (), так как это насчитывало всех связанных комментариев, и я хотел только подсчитать активных связанных комментариев.

Решение Даниэля не сработало, потому что оно отфильтровывало сообщения, которые не имели комментариев.Я не хочу отфильтровывать сообщения, только неактивные комментарии.

Если у кого-то есть лучшее решение, я с радостью проголосую и наилучшим образом отвечу вам!

...