5

我正在尝试使用 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”的评论。谷歌和 Django 文档在这里没有帮助我。有没有人遇到过并解决了这个问题?

4

3 回答 3

5

您只需要is_active在进行注释之前进行过滤:

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

请参阅此处的说明

于 2010-09-29T18:13:13.863 回答
3

根据您使用的数据库,有两种变体。如果您使用MySQL,则解决方案简单而优雅:

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

这是因为在数据库中布尔字段是整数,True 是 1,False 是 0。

但这仅适用于 MySQL并且仅适用于布尔字段。完成适用于所有数据库并可以进行更复杂检查的工作的更通用方法是使用插入一点“hacky”的小 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/。它在保加利亚语上,但我的网站使用谷歌翻译。翻译不是很好,但可能有助于理解为什么会这样。

于 2013-06-14T07:08:33.273 回答
3

这就是我必须在我的 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(),因为它计算了所有相关评论,而我只想计算活动的相关评论。

丹尼尔的解决方案不起作用,因为它过滤掉了没有评论的帖子。我不想过滤掉任何帖子,只是不活跃的评论。

如果有人有更好的解决方案,我很乐意投票并最佳回答您!

于 2010-09-30T18:50:32.713 回答