如何使用annotate()来计算Django中相关模型的子集?

mit*_*chf 4 django annotate django-models

我正在尝试使用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)
Run Code Online (Sandbox Code Playgroud)

在视图中,我试图注释一个查询集:

queryset=Post.objects.all().annotate(num_comments=Count('comment', distinct=True))
Run Code Online (Sandbox Code Playgroud)

以上计算与帖子相关的所有评论,而我只想计算"is_active"评论.Google和Django文档在这里没有帮助我.有没有人解决过这个问题?

Dan*_*man 5

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

Post.objects.filter(comment__is_active=True).annotate(num_comments=Count('comment'))
Run Code Online (Sandbox Code Playgroud)

请参阅此处的说明.


mit*_*chf 3

这就是我必须“注释”我的帖子查询集上的活跃评论数量的方式:

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
     """
     },)
Run Code Online (Sandbox Code Playgroud)

不漂亮,但它有效。正如我在上面的评论中提到的,不可能为此使用内置聚合函数 annotate() ,因为它会计算所有相关评论,而我只想计算活跃的相关评论。

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

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