美文网首页Django学习django首页投稿(暂停使用,暂停投稿)
Django Blog 统计某个分类下有多少篇文章的优雅实现方法

Django Blog 统计某个分类下有多少篇文章的优雅实现方法

作者: 追梦人物 | 来源:发表于2016-08-06 16:12 被阅读2094次

    假设我们有如下的 Model :

    class Article(models.Model):
        title = models.CharField('标题', max_length=200)
        body = models.TextField('正文')
        created_time = models.DateTimeField('创建时间', auto_now_add=True)
        
        author = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='作者', on_delete=models.CASCADE)
        category = models.ForeignKey('Category', verbose_name='分类', on_delete=models.CASCADE)
        tags = models.ManyToManyField('Tag', verbose_name='标签集合', blank=True)
    
        def __str__(self):
            return self.title
    
    class Category(models.Model):
        name = models.CharField('分类名', max_length=30)
    
        def __str__(self):
            return self.name
    
    class Tag(models.Model):
        name = models.CharField('标签名', max_length=30)
    
        def __str__(self):
            return self.name
    

    可以看到 Article 与 Author,Category 是外键关联的,而和 Tag 多对多的关系。有时候我们有这样的需求:在模板中显示全部的 category,author,tag,同时还要对应显示与其关联的 Article 数量,例如:

    • 分类一 ( 10 )
    • 分类二 ( 15 )
    • 分类三 ( 8 )

    由于 Article 和 Category 外键关联的,在模板中我们可以使用 {{ category_instance.article_set.count }} 取得 category_instance 这一特定分类下关联的全部 Article 数量,但是缺点也很明显,无法在模板标签中传递参数,count 方法将返回全部关联的文章数目。有时我们想要更加精细化一点的显示,比如统计某个分类下全部 Article 发表时间在某个时间点后的文章,而如果该分类对应的文章数为 0 ,我们在模板中则不显示该分类。看上去挺复杂的逻辑,Django 的 annote 方法一句话可以解决我们的问题。

    使用:

    from django.db.models.aggregates import Count
    
    category_list = Category.objects.filter(article__created_time_gt=(2015,1,1)).annotate(
        num_articles=Count('article')).filter(num_articles__gt=0)
    

    annote 的功能是根据某个规则给 queryset 中的每一个元素(例如我们这里的是 category)添加一个属性。queryset 是从数据库中查询到的一组数据的集合,Django 将其封装在 QuerySet 对象里。

    这句话的意思的,首先对 Category 做筛选(filter),即筛选出其对应的全部文章发表时间大于 2015年1月1日的 category记录(article__created_time_gt=(2015,1,1)) ,然后为筛选出来的每一个条 category 记录添加了一个属性:num_articles(num_articles=Count('article'))),Count 方法为我们计算了每一条 catogory 下对应的 article 数量,最后再对这组记录筛选出对应文章数量大于 0 的记录,即满足了我们上述要求。同理可以对 Author,Tag 做类似筛选。

    值得注意的是第一个 filter 和 annotate 的顺序不能乱,否则可能无法得到我们预期的结果。

    相关文档位于:QuerySet Method referenceAggregation

    灵活使用这些方法将使我们复杂的查询需求代码变得更加高效和简短。

    相关文章

      网友评论

      • 533add56d55b:视图函数获取分类文章的数量后 前端页面怎么做呢??
        533add56d55b:@追梦人物 好的! 谢谢
        追梦人物:@Bowen_ 和模型的属性一样调用就可以了
      • 颠狂书生:学习了你的django blog的教程,也在github上下载了原代码,按你的说明在本机上运行了 http://127.0.0.1:8000/ ,只能看到一个空白的模板,那些分类、归档还是登录的例子都看不到,楼主是没更新吗?
        追梦人物:@2flyor2die 嗯,目前在做其他东西,暂时没有更新。

      本文标题:Django Blog 统计某个分类下有多少篇文章的优雅实现方法

      本文链接:https://www.haomeiwen.com/subject/embksttx.html