2010-09-29 34 views
2

我正在尝试使用Django的注释功能将相关模型的计数添加到查询集。但是,我不想要完整的相关对象数,我只想对活动数进行计数(即“is_active = True”)。我无法弄清楚如何过滤计数。我如何使用annotate()来计算Django中相关模型的子集?

(简化)相关机型:

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

这是我不得不“注释”的积极评论的数量在我的岗位查询集:

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(),因为它计数了所有相关评论,我只想计算活动相关评论。

Daniel的解决方案没有奏效,因为它滤除了没有评论的帖子。我不想过滤掉任何帖子,只是非活动的评论。

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

+0

注意:当我在同一个查询集上混合使用.annotate()和.extra()时,遇到了一些麻烦(例如,额外数据上的“order_by”失败)。我最终将annotate()中的count移到了extra()函数中,然后我的“order_by”工作。我可以澄清是否有人遇到类似的问题。 – mitchf 2010-09-30 19:17:15

4

你只需要做注解之前is_active过滤:

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

the explanation here

+0

谢谢丹尼尔!当我使用此查询集显示包含数字或注释的帖子列表时,它只会拉取至少包含一个相关活动注释的帖子。没有评论的帖子不在查询集中,这不是我想要的。好消息是:所包含帖子的评论是正确的。我错过了什么吗? – mitchf 2010-09-29 18:28:57

+1

经过一段时间的关于这个问题的讨论后,我不相信有一种方法可以解决我的问题,然后使用过滤器和注释/计数。据我所知,我将不得不陷入SQL ......恶作剧。 – mitchf 2010-09-30 03:26:25

3

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

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

这工作,因为在数据库中布尔字段是整数,真为1,假为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/。这是保加利亚语,但我的网站使用谷歌翻译。翻译不是很好,但可能有助于理解为什么这会起作用。

相关问题