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;从服务…

计算机无法安装64位操作系统,为什么我的win7旗舰版service Pack 1 64位操作系统 无法安装(KB2670838) 这个更新...

您好&#xff01;我了解到您遇到关于这边的问题请问无法安装是否出现了什么错误代码提示呢&#xff1f;请参考以下的步骤解决按WindowsR打开cmd里使用下面的命令关闭相关的一些服务&#xff1a;net stop wuauservnet stop cryptSvcnet stop bitsnet stop msiserver完成后&#…

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

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

函数的调用规则(__cdecl,__stdcall,__fastcall,__pascal)

关于函数的调用规则&#xff08;调用约定&#xff09;&#xff0c;大多数时候是不需要了解的&#xff0c;但是如果需要跨语言的编程&#xff0c;比如VC写的dll要delphi调用&#xff0c;则需要了解。 microsoft的vc默认的是__cdecl方式&#xff0c;而windows API则是__stdcall&a…

Linux 下的/usr/bin /usr/sbin /usr/local/bin /usr/local/sbin区别

1、/bin 是所有用户都可以访问并执行的可执行程序。包括超级用户及一般用户。 供所有用户&#xff08;包括root用户和一般用户&#xff09;使用的基本命令&#xff0c;主要有cat,chmod,date,cp,bash等等常用的命令。 2、/usr/bin&#xff1a;系统预装的可执行程序&#xff0c;…

alpha测试和betal测试

如果一个软件是为许多客户开发的&#xff08;例如&#xff0c;向大众公开出售的盒装软件产品&#xff09;&#xff0c;那么绝大多数软件开发商都使用被称为Alpha测试和Beta测试的过程&#xff0c;来发现那些看起来只有最终用户才能发现的错误。 Alpha测试由用户在开发者的场所进…

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

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

sqlserver视图

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

非root用户sudo_ssh免密钥

非root用户sudo_ssh免密钥 目标&#xff1a;从服务器上ssh登陆后sudo免密钥执行相应的命令 环境介绍&#xff1a; 192.168.65.128 my1-222 192.168.65.129 my2-223 192.168.65.130 web224# 步骤一&#xff1a; # 每个节点执行(不是必须&#xff0c;但是建议这样做) cat …

复旦大学和吉大计算机考研选哪个,2016复旦大学VS吉林大学 基于排名角度的比较?...

复旦大学好还是吉林大学好首先&#xff0c;2016复旦大学好还是吉林大学好是近日问得较多的问题之一&#xff0c;小伙伴们有的从吉林大学和复旦大学的地理位置优势角度进行分析&#xff0c;有的从吉林大学和复旦大学的强势专业角度进行PK&#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…

白盒测试详解

通常把测试数据和预期的输出结果称为测试用例。 &#xff08;一&#xff09;逻辑覆盖 是对一系列测试过程的总称&#xff0c;这组测试过程逐渐进行越来越完整的通路测试。 1.语句覆盖 语句覆盖的含义是&#xff0c;选择足够多的测试数据&#xff0c;使被测程序中每个语句至少…

git 的安装以及使用:是一个开源的分布式版本控制系统,可以对项目进行版本管理。 早期是linux之父用来管理linux系统源代码的(linux是和windows一样操作系统 开源免费的操作...

## 总结 - 学会使用基本的git命令 管理源代码- 学会去github创建仓库 并将代码上传到github的仓库 (有待完成 回家有网再push)- 了解本地的.git和服务器github的.git的关系 是两个仓库 一个是本地 一个是服务器 需要使用一句命令来关联 git remote add origin 远端的.git的地址…

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

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

2013计算机二级试题,2013全国计算机二级上机考试试题46-100套试题

*第46 套上机考试试题一、基本操作题**请根据以下各小题的要求设计Visual Basic 应用程序(包括界面和代码)。(1)在名称为Form1、标题为“框架练习”的窗体上*画一个名称为Frame1、标题为“字体”的框架控件&#xff1b;在框架中画两个单选按钮&#xff0c;名称分别为Option1、O…

黑盒测试详解

黑盒测试着重测试软件功能。黑盒测试并不能取代白盒测试&#xff0c;它是与白盒测试互补的测试方法&#xff0c;它很可能发现白盒测试不易发现的其他类型的错误。白盒测试在测试过程的早期阶段进行&#xff0c;而黑盒测试主要用于测试过程的后期。 黑盒测试力图发现下述类型的…

linux中rpm、yum、apt-get的关系

Linux中yum和apt-get用法及区别 一般来说著名的linux系统基本上分两大类&#xff1a; 1.RedHat系列&#xff1a;Redhat、Centos、Fedora等 2.Debian系列&#xff1a;Debian、Ubuntu等 RedHat 系列 1 常见的安装包格式 rpm包,安装rpm包的命令是“rpm -参数” 2 包管理工具 y…

echart事件

reference&#xff1a; https://www.w3cschool.cn/echarts_tutorial/echarts_tutorial-7o3u28yh.html var mychart echarts.init(document.getElementById(abc)); var option {....}//忽略了具体参数 mychart.on(click,function(params){console.log(params);console.log(para…

三网融合情况下,实时语音通信技术的研究

随着技术和标准的不断成熟,伴随着“三网合一”的大潮,VoIP可望成为下一代电信基础设施结构的杨心,使未来各电信业务综合统一在IP网络上成为可能,导致数据的融合和未来电信市场的重组,并带来新的经济模式和价值链。 Internet在全世界范围内的快速发展和语音信号处理技术的进步,促…

计算机操作系统指导书,《计算机操作系统》实验指导书-2015

q.num;System.out.println(\已生产第&#xff1a;\个产品!\try {Thread.currentThread().sleep(100); } catch (InterruptedException e) {e.printStackTrace(); }q.notify(); }else {try {System.out.println(\ q.wait();} catch (InterruptedException e) {e.printStackTrace…