Diango博客--17.统计各个分类和标签下的文章数

文章目录

    • 0.思路引导
    • 1.Model 回顾
    • 2.数据库数据聚合
    • 3.使用 Annotate
    • 4.在模板中引用新增的属性

0.思路引导

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

1.Model 回顾

回顾一下我们的 model 代码,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.titleclass Category(models.Model):name = models.CharField('分类名', max_length=100)

我们知道从数据库取数据都是使用模型管理器 objects 的方法实现的。比如获取全部分类是:Category.objects.all() ,假设有一个名为 test 的分类,那么获取该分类的方法是:Category.objects.get(name=‘test’) 。

objects 除了 all、get 等方法外,还有很多操作数据库的方法,而其中有一个 annotate 方法,该方法可以帮我们实现本文所关注的统计分类下的文章数量的功能。

2.数据库数据聚合

annotate 方法在底层调用了数据库的数据聚合函数,下面使用一个实际的数据库表来帮助我们理解 annotate 方法的工作原理。

在 Post 模型中我们通过 ForeignKey 把 Post 和 Category 关联了起来,这时候它们的数据库表结构就像下面这样:

Post 表:
在这里插入图片描述Category 表:

在这里插入图片描述
1)当 Django 要查询某篇 post 对应的分类时,比如 post 1,首先查询到它分类的 id 为 1,然后 Django 再去 Category 表找到 id 为 1 的那一行,这一行就是 post 1 对应的分类。

2)反过来,如果要查询 category 1 对应的全部文章呢?category 1 在 Category 表中对应的 id 是 1,Django 就在 Post 表中搜索哪些行的 category_id 为 1,发现前 3 行都是,把这些行取出来就是 category 1 下的全部文章了。

3)同理,这里 annotate 做的事情就是把全部 Category 取出来,然后去 Post 查询每一个 Category 对应的文章,查询完成后只需算一下每个 category id 对应有多少行记录,这样就可以统计出每个 Category 下有多少篇文章了。

4)把这个统计数字保存到每一条 Category 的记录就可以了(当然并非保存到数据库,在 Django ORM 中是保存到 Category 的实例的属性中,每个实例对应一条记录)。

3.使用 Annotate

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

文件位置:blog/templatetags/blog_extras.py

from django.db.models.aggregates import Count
from blog.models import Category@register.inclusion_tag('blog/inclusions/_categories.html', takes_context=True)
def show_categories(context):category_list = Category.objects.annotate(num_posts=Count('post')).filter(num_posts__gt=0)return {'category_list': category_list,}

1)这个 Category.objects.annotate 方法和 Category.objects.all 有点类似,它会返回数据库中全部 Category 的记录,但同时它还会做一些额外的事情,在这里我们希望它做的额外事情就是去统计返回的 Category 记录的集合中每条记录下的文章数。

2)代码中的 Count 方法为我们做了这个事,它接收一个和 Categoty 相关联的模型参数名(这里是 Post,通过 ForeignKey 关联的),然后它便会统计 Category 记录的集合中每条记录下的与之关联的 Post 记录的行数,也就是文章数,最后把这个值保存到 num_posts 属性中。

3)此外,我们还对结果集做了一个过滤,使用 filter 方法把 num_posts 的值小于 1 的分类过滤掉。因为 num_posts 的值小于 1 表示该分类下没有文章,没有文章的分类我们不希望它在页面中显示。

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

@register.inclusion_tag('blog/inclusions/_tags.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,}

4.在模板中引用新增的属性

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

文件位置:templates/blog/inclusions/_categories.html

<div class="widget widget-category"><h3 class="widget-title">分类</h3><ul>{% for category in category_list %}<li><a href="{% url 'blog:category' category.pk %}">{{ category.name }} <span class="post-count">({{ category.num_posts }})</span></a></li>{% empty %}暂无分类!{% endfor %}</ul>
</div>

文件位置:templates/blog/inclusions/_tags.html

<div class="widget widget-tag-cloud"><h3 class="widget-title">标签云</h3><ul>{% for tag in tag_list %}<li><a href="{% url 'blog:tag' tag.pk %}">{{ tag.name }} <span class="post-count">({{ tag.num_posts }})</a></li>{% empty %}暂无标签!{% endfor %}</ul>
</div>

也就是在模板中通过模板变量 {{ category.num_posts }}以及 {{ tag.num_posts }}显示 num_posts 的值。

开启开发服务器,可以看到分类名后正确地显示了该分类下的文章数了,而没有文章分类则不会在分类列表中出现。

效果展示如下:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/452386.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTTP协议中request报文请求方法和状态响应码

一个HTTP请求报文由4部分组成&#xff1a; 请求行&#xff08;request line&#xff09;请求头部&#xff08;header&#xff09;空行请求数据下图给出了请求报文的一般格式&#xff1a; 请求行中包括了请求方法&#xff0c;常见的请求方法有&#xff1a; GET&#xff1a;从服务…

bmon:一个强大的网络带宽监视和调试工具

bmon 是类 Unix 系统中一个基于文本&#xff0c;简单但非常强大的 网络监视和调试工具&#xff0c;它能抓取网络相关统计信息并把它们以用户友好的格式展现出来。它是一个可靠高效的带宽监视和网速估测工具。 它能使用各种输入模块读取输入&#xff0c;并以各种输出模式显示输出…

计算机d盘无法格式化,四种方法解决D盘无法格式化问题

不少朋友系统出现故障&#xff0c;几乎都是选择重装系统的方法来解决问题。系统重装后&#xff0c;不少朋友觉得D盘没有什么重要的东西&#xff0c;就想将其格式化&#xff0c;可是系统出现windows无法格式该驱动器的提示&#xff0c;这是怎么回事呢&#xff1f;D盘无法格式化要…

sqlserver视图

作用 ①简化了操作&#xff0c;把经常使用的数据定义为视图。 ②安全性&#xff0c;用户只能查询和修改能看到的数据。 ③逻辑上的独立性&#xff0c;屏蔽了真实表的结构带来的影响。 对视图的修改&#xff1a;单表视图一般用于查询和修改&#xff0c;会改变基本表的数据&#…

Diango博客--18.使用 Fabric 自动化部署 Django 项目

文章目录1.本地安装 Fabric2.部署过程回顾3.完善项目配置4.修改 BASE_DIR 配置项5.设置 Supervisor 环境变量6.编写 Fabric 脚本7.执行 Fabric 自动部署脚本1.本地安装 Fabric $ pipenv install fabric --dev 报错&#xff1a; An error occurred while installing django-pure…

自断前程,未来80%IT工作将实现自动化

技术人员革了自己的命&#xff1f; 在上周的Structure大会上&#xff0c;硅谷著名风险投资人、亿万富翁唯诺德称未来80%的IT工作都将被AI系统所替代。不过&#xff0c;唯诺德好像并不担心&#xff0c;相反他补充了一句“我觉得很兴奋。”唯诺德表示自己并非危言耸听&#xff0c…

转://Linux Multipath多路径配置与使用案例

在Linux平台一部分存储产品使用操作系统自带的多路径软件&#xff0c;包括最常见的HP和IBM的部分存储产品&#xff0c;在Linux自带的多路径软件叫做multipath&#xff0c;这篇文章以HP EVA系列存储在Linux平台的使用为例&#xff0c;详细的在Linux平台配置和使用多路径。 那么问…

Windows中安装MongoDB以及studio3t

文章目录1.安装MongoDB2.配置并启动MongoDB3.使用studio3t连接mongodb1.安装MongoDB 运行 mongodb-win32-x86_64-2008plus-ssl-v3.4-latest-signed.msi 2.配置并启动MongoDB 创建几个文件夹具体如下&#xff1a; 1&#xff09;数据库路径&#xff08;data目录&#xff09; 2…

为旗下硬件产品服务,LG推出基于SLAM技术的3D摄像头

LG官方则表示&#xff0c;集成了LG的3D摄像头和SLAM技术的单个模块性价比很高。 今年3月份的时候&#xff0c;LG在MWC 2017上展示其和Valve合作的VR头显&#xff0c;最近他们宣布将基于AR公司Augmented Pixels的技术开发一个3D摄像头模块&#xff0c;来辅助他们的各种硬件产品…

VS工程切换cuda版本

在工程面板&#xff0c;切换到类视图&#xff0c;选中项目&#xff0c;右键菜单选择【生成自定义&#xff08;B&#xff09;…】&#xff0c;弹出下面窗口 在窗口勾选上CUDA版本&#xff0c;即可切换 转载于:https://www.cnblogs.com/xingzhensun/p/9154094.html

揭秘Microsoft Bing与Google搜索背后的故事

导读&#xff1a;Google搜索引擎已经赢得全球范围的赞誉&#xff0c;而这一切都要归功于Google开创性的MapReduce。Google搜索引擎算法只是其搜索引擎的一部分&#xff0c;在后台支持Google算法的基础设施才是真正的幕后英雄&#xff0c;其基础设施可快速的索引链接成千上万台普…

计算机图画大赛作品六年级,打字能手显本领,电脑绘画展风采——记陆埠二小举行电脑绘画和电脑打字比赛...

为了提高小学生的计算机应用水平&#xff0c;培养学生动手能力和综合素质&#xff0c;提升学生的信息素养&#xff0c;2019年5月23日、24日中午&#xff0c;陆埠镇第二小学举行了三四年级电脑打字和五六年级电脑绘画比赛。本次比赛&#xff0c;3--6年级每班中选出3名学生参加&a…

变量在原型链中的查找顺序

js原型链 下面是一道js题目&#xff1a;[javascript] view plaincopy function C1(name){ if(name){ this.name name; } } function C2(name){ this.name name; } function C3(name){ this.name name || "John"; } C1.p…

基于SpringBoot + Vue的图书管理系统

功能概述 该图书管理系统提供了一系列功能&#xff0c;包括图书管理、图书类型管理、读者借阅归还图书、用户管理和重置密码等。 在图书管理功能中&#xff0c;管理员可以方便地进行图书信息的管理。他们可以添加新的图书记录&#xff0c;包括书名、作者、出版社、ISBN等信息&a…

交换机的工作转发原理

交换机通常是运行在网络OSI七层模型的第二层数据链路层&#xff0c;如图中&#xff0c;第三层网络层通常是路由器运行在该层 今天我们来看看&#xff0c;交换机的工作转发原理是什么样的。 交换机既然是利用端口进行网络数据传输&#xff0c;那么它是如何识别数据是谁给谁的呢…

八个最好的轻量级Linux发行版

如果你在苦恼老旧的硬件无法利用&#xff0c;如果你想要一个能够在不是很大的记忆棒上运行的系统&#xff0c;如果你想要在桌面端上运行200个虚拟机&#xff0c;那么你可以考虑一些“迷你”的Linux发行版。 曾经在08年介绍过当时的十大轻量级Linux&#xff0c;现在已经是2010年…

面向对象——三层架构(表现层、业务层、持久层)

① 持久层&#xff1a;采用DAO模式&#xff0c;建立实体类和数据库表映射&#xff08;ORM映射&#xff09;。也就是哪个类对应哪个表&#xff0c;哪个属性对应哪个列。持久层 的目的就是&#xff0c;完成对象数据和关系数据的转换。 ② 业务层&#xff1a;采用事务脚本模式。将…

VMware安装Centos7后有线线缆被拔出

背景&#xff1a;在win10 系统中的虚机软件VMware Workstation中安装CentOS7桌面版&#xff0c;安装过程中没有设置网络 1.确认你win10系统打开了这两个服务&#xff1a;VMware DHCP Service和VMware NAT Service 方法&#xff1a;电脑——右键——管理——服务和应用程序——服…

SpringCloud |第二篇: 服务消费者(Ribbon)

2019独角兽企业重金招聘Python工程师标准>>> 一、Ribbon简介 Ribbon是Netflix发布的开源项目&#xff0c;主要功能是提供客户端的软件负载均衡算法&#xff0c;将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配置项如连接超时&#xff0c;重试…

万维网www

WWW是环球信息网的缩写&#xff0c;&#xff08;亦作“Web”、“WWW”、“W3”&#xff0c;英文全称为“World Wide Web”&#xff09;&#xff0c;中文名字为“万维网”&#xff0c;"环球网"等&#xff0c;常简称为Web。 分为Web客户端和Web服务器程序。 WWW可以让W…