统计各个分类和标签下的文章数

在我们的博客侧边栏有分类列表和标签列表,显示博客已有的全部文章分类。现在想在分类名和标签名后显示该分类或者标签下有多少篇文章,该怎么做呢?最优雅的方式就是使用 django 的 annotate 方法。

Model 回顾
回顾一下我们的 model 代python123码,python下载安装教程django 博客有一个 Post 和 Category 模型,分别表示文章和分类:

blog/models.py

class Post(models.Model):

title = models.CharField('标题', max_length=70)
body = models.TextField('正文')
category = models.ForeignKey(Category, verbose_name='分类', on_delete=models.CASCADE)
# 其它属性...
def __str__(self):
return self.title

class Category(models.Model):

name = models.CharField('分类名', max_length=100)

复制代码
我们知道从数据库取数据都是使用模型管理器 objects 的方法实现的。比python是什么意思如获取全部分类是:Category.objects.all() ,假设有一个名为 test 的分类,那么获取该分类的方法是:Category.objects.get(name='test') 。opython可以做什么工作bjects 除了 al数据库有哪几种l、get 等方法外,还有很多操作数据库的方法,而其中有一个 annotate 方法,该方法正可以帮我们实现本文所关注的统计分类下的文章数量的功能。

数据库数据聚python爬虫
annotate 方法在底层调用了数据库的数据聚合函数,下面使用一个实际的数据库表来帮助我们理解 annotate 方法的工作原理。在 Post 模型中我们通过 ForeignKeypython是什么意思 把 Post 和 Category 关联了起来,这时候它们的数据库表结构就像下面这样:

Postpython123平台登录 表:

id title body categopython可以做什么工作ry_id
1 post 1 ... 1
2 post 2 ... 1
3 post 3 ... 1
4 post 4 ...python是什么意思 2
Category 表:

name id
category 1 1
category 2 2
这里前 3 篇文章属于 category 1,第 4 篇文章属于 category 2。

当 Django 要查询某篇 p数据库增删改查基本语句ost 对应的分类时,比如 post 1,首先查询到它分类的 id 为 1,然后 Django 再去 Category 表找到 id 为 1 的那一行,这一行就是 po数据库st 1 对应的分类。反过来,如果要查询 category 1 对应的全部文章呢?catpython可以做什么工作egory 1 在 Category 表中对应的 ipython是什么意思dpython123 是 1,Django 就在 Post 表中搜索哪些行的 ca数据库原理及应用tegory_id 为 1,发现前 3 行都是数据库软件,把这些行取出来就是 category 1 下的全部文数据库增删改查基本语句章了。同理python爬虫,这里 annotate 做的事情就是把全部 Category 取出来,然后去 Post 查询每一个 Category 对应的文章,查询完成后只需算一下每个 category id 对应有多少行记录,这样就可以统计出每个 Category 下有多少篇文章了。把这个手机号码买卖统计数字保存到每一条 Category 的记录就可以了(当然并非保存到数据库,在 Django ORM 中是保存到 Category 的实例的属python下载安装教程性中,每个实例对应一条记录)。

使用 Annotate
以上是原理方面的分析,具体到 Django 中该如何用呢?在我们的博客数据库系统工程师中,获取侧边栏python编程的分类列表的方法写在模板标签 get_categories 里,因此我们修改一下这个函数,具体代码如下:

blog/templatetags/blog_extras.py

from django.db.models.aggregates import C数据库系统的核心是ount
from blogpython.mpython123odels import Category

@register.inclusion_tag('blog/inclusions/_categories.html', takes_contpython123平台登录ext=True)
def show_categories(context):

category_list = Category.objects.annotate(num_posts=Count('post')).filter(num_posts__gt=0)
return {
'category_list': category_list,
}

复制代码
这个 Category.objects.annotate 方法和 Category.objects.all 有点类似,它会数据库查询语句返回数据库中全部 Category 的记录,但同时它还会做一些额外的事情,在这里我们希望它做的额外python代码画樱花事情就是去统计返回的 Category 记录的集合中每条记录下的文章数。代码中的 Count 方法为我们做了这个事,它接收一个和 Categoty 相关联的模型参数名(这里是 Post,通数据库系统工程师过 ForeignKey 关联的),然后它数据库软件便会统计 Category 记录的集合中每条记录下的与之关联的 Post 记录的行数,也就是文章数,最后把这个值保存到 num_posts 属性中。

此外,我们还对结果集做python爬虫了一个过滤,使用 filter 方法把 num_posts 的值小于 1 的分类过滤掉。因为 num_posts 的值小数据库中未查询于 1 表示该分类下没有文章,没有文章的分类我们不希望它在页面中显示。关于 filter 函数以及查询表达式(双下划线)在之前已经讲过,具体请参python可以做什么工作考 分类、归档和标数据库原理及应用签页。

同理,tags 也可以做同样的操作。

@register.inclusion_tag('blog/inclusions/_ta数据库系统概论第五版课后答案gs.html', takes_context=True)
def show_tags(context):

tag_list = Tag.objects.annotate(num_posts=Count('post')).filter(num_posts__gt=0)
return {
'tag_list': tag_list,
}

复制代码
在模板中引用新增的属性
现在在 Category 和 Tag 列表中每一项都新增了一个 num_posts 属性记录该 Category 下的文章数量,我们就可以在模板中引用这个属性来显示分类下的文章数量python123了。

templates/blog/inclusipython是什么意思ons/_categories.html

分类

  • {% for category in category_list %python爬虫}
  • {{ category.name }} ({{ category.num_posts }})
    {% empty %}
    暂无分类!
    {% endfor %}

复制代码
标签也是一样:

templates/blog/inclusions/_tags.html

标签云

  • {% for tag in tag_list %}
  • {{ tag.name }} ({{ tag.num_posts }})
    {% empty %}
    暂无标签!
    {% endfor %}数据库有哪几种

复制代码
也就是在模板中通过模板变量python可以做什么工作 {数据库管理系统{ category.num_posts数据库管理系统 }} 显示 num_posts 的值。开启开发服务器,可以看到分类名python可以做什么工作后正确地显示了该分类下的文章数了,而没有文章分类则不会在分类列表中出现。