Django Blog 统计某个分类下有多少篇文章的优雅实现方法
admin
2023-07-30 21:34:01
0

假设我们有如下的 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 reference 和 Aggregation

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

相关内容

热门资讯

Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
Apache Doris 2.... 亲爱的社区小伙伴们,我们很高兴地向大家宣布,Apache Doris 2.0.0 版本已于...
python清除字符串里非数字... 本文实例讲述了python清除字符串里非数字字符的方法。分享给大家供大家参考。具体如下: impor...