Django模板中的Count方法无法按预期工作

时间:2014-06-09 09:39:25

标签: django django-templates django-views django-class-based-views class-based-views

我正在构建一个新闻应用,允许会员发表文章评论。我想在模板中显示文章,并显示每篇文章的评论数量。我尝试使用count方法,但它检索了我的注释表中的注释总数,而不是特定文章的注释数。

#models.py
class Article(models.Model):
    #auto-generate indices for our options
    ENTRY_STATUS = enumerate(('no', 'yes'))
    #this will be a foreign key once account app is built
    author = models.CharField(default=1, max_length=1)
    category = models.ForeignKey(Category)
    title = models.CharField(max_length=50)
    entry = models.TextField()
    dateposted = models.DateTimeField(default=timezone.now, auto_now_add=True)
    draft = models.IntegerField(choices=ENTRY_STATUS, default=0)
    lastupdated = models.DateTimeField(default=timezone.now, auto_now=True)

    #prevents the generic labeling of our class as 'Classname object'
    def __unicode__(self):
        return self.title


class Comment(models.Model):
    #this will be a foreign key once account app is built
    author = models.CharField(default=1, max_length=1)
    article = models.ForeignKey(Article)
    dateposted = models.DateTimeField(auto_now_add=True)
    comment = models.TextField()

    def __unicode__(self):
        #returns the dateposted as a unicode string
        return unicode(self.dateposted)

#templates/list_articles.html
{% for comment in comments %}
    {% if comment.article_id == article.id %}
        {% if comments.count < 2 %}
            #this is returning all comments in comment table
            <b>{{ comments.count }} comment</b>
        {% else %}
            <b>{{ comments.count }} comments</b>
        {% endif %}
    {% endif %}
{% endfor %}

到目前为止我见过的所有示例都是手动提供过滤的值(例如Comment.objects.filter(article_id=x).count())在我的情况下,我只能通过模板访问。

#views.py
class ArticlesListView(ListView):
    context_object_name = 'articles'
    # only display published pieces (limit 5)
    queryset = Article.objects.select_related().order_by('-dateposted').filter(draft=0)[:5]
    template_name = 'news/list_articles.html'

    # overide this to pass additional context to templates
    def get_context_data(self, **kwargs):
        context = super(ArticlesListView, self).get_context_data(**kwargs)
        #get all comments
        context['comments'] = Comment.objects.order_by('-dateposted')
        #get all article photos
        context['photos'] = Photo.objects.all()
        #context['total_comments'] = Comment.objects.filter(article_id=Article)
        return context

我的预期结果是列出所有文章,并在每篇文章下面对该文章进行评论汇总(例如第1条:第4条评论,第5条:1条评论等......)现在我和#39; m getting:第1条:第4条评论,第5条:第4条评论(即使第5条只有1条评论)

感谢任何帮助。我花了5个小时阅读文档,但每个示例都手动提供了一个值来过滤。

1 个答案:

答案 0 :(得分:4)

我不确定为什么你会发现这种意外。 comments 全部评论,因此当然comments.count是所有评论的计数。怎么会这样呢?你不能在任何地方过滤它们。

然而,这是一种非常可怕的做事方式。绝对没有理由将所有评论传递给模板,然后遍历它们以检查它们是否是正确的文章。您有从Comment到Article的外键,因此您应该使用反向关系来获取相关的通知。

从您的视图中完全忽略Comment查询,并在模板中执行此操作(替换整个嵌套fors和ifs块):

{{ article.comment_set.count }}

然而,这会对每篇文章进行一次计数查询。更好的解决方案是使用注释,因此您可以在一个查询中完成所有操作。更改您的查询集以添加相关注释的注释计数:

from django.db.models import Count

class ArticlesListView(ListView):
    queryset = Article.objects.select_related().annotate(comment_count=Count('comments')).order_by('-dateposted').filter(draft=0)

现在你可以做到

{{ article.comment_count }}