我正在尝试使用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文档在这里没有帮助我。有没有人解决过这个问题?
答案 0 :(得分:5)
在执行注释之前,您只需要在is_active
上进行过滤:
Post.objects.filter(comment__is_active=True).annotate(num_comments=Count('comment'))
答案 1 :(得分:3)
根据您使用的数据库,有两种变体。如果您使用 MySQL ,解决方案简单而优雅:
Post.objects.annotate(num_comments=Sum('comment.is_active'))
这是有效的,因为在数据库中,布尔字段是整数,True是1,False是0。
但是这只适用于仅适用于MySQL ,并且仅适用于布尔字段。执行适用于所有数据库并可以执行更复杂检查的工作的更一般方法是使用一点点插入一点“hacky'”
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/。这是保加利亚语,但我的网站使用谷歌翻译。翻译不是很好,但可能有助于理解其工作原理。
答案 2 :(得分:2)
这就是我必须“注释”我的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(),因为它计算了所有相关的注释,我只想计算活跃相关评论。
丹尼尔的解决方案不起作用,因为它过滤掉了没有评论的帖子。我不想过滤掉任何帖子,只是不活跃的评论。
如果有人有更好的解决方案,我很乐意投票并最好地回答你!