基于Django统计博客文章阅读量


Posted in Python onOctober 29, 2019

如何精确地记录一篇文章的阅读量是一个比较复杂的问题,不过对于我们的博客来说,没有必要记录的那么精确。因此我们使用一种简单但有效的方式来记录博客文章的阅读量:文章每被浏览一次,则其阅读量 +1,即所谓的文章页面 PV(Page View)数。虽然简单粗暴,但却高效实用。

增加新字段

为了记录文章的浏览量,需要在文章的数据库表中新增一个用于存储阅读量的字段。因此给博客文章的模型新增一个 views 字段:

blog/models.py

class Post(models.Model):
  # ... 其它已有字段
  # 新增 views 字段记录阅读量
  views = models.PositiveIntegerField(default=0, editable=False)

注意 views 字段的类型为 PositiveIntegerField,该类型的值只允许为正整数或 0,因为阅读量不可能为负值。初始化时 views 的值为 0。将 editable 参数设为 False 将不允许通过 django admin 后台编辑此字段的内容。因为阅读量应该根据被访问次数统计,而不应该人为修改。

增加模型方法

一旦用户访问了某篇文章,这时就应该将 views 的值 +1,这个过程最好由 Post 模型自己来完成,因此再给模型添加一个自定义的方法:

blog/models.py

class Post(models.Model):
  # ... 其它已有字段
  # 新增 views 字段记录阅读量
  views = models.PositiveIntegerField(default=0)  
  # ... 其它已有的模型方法
  def increase_views(self):
    self.views += 1
    self.save(update_fields=['views'])

increase_views 方法首先将自身对应的 views 字段的值 +1(此时数据库中的值还没变),然后调用 save 方法将更改后的值保存到数据库。注意这里使用了 update_fields 参数来告诉 Django 只更新数据库中 views 字段的值,以提高效率。

你也许担心如果两个人同时访问一篇文章,更改数据库中的阅读量字段的值时会不会冲突?其实不必担心,我们本来就不是精确地统计阅读量,而且个人博客的流量通常也不会很大,所以偶尔的冲突导致的数据误差是可以忽略不计的。

迁移数据库

一旦更改了模型,就需要迁移数据库,以便让 Django 将更改反应到数据库中。在项目根目录运行如下两条命令:

$ pipenv run python manage.py makemigrations
$ pipenv run python manage.py migrate

关于数据库的迁移,具体可以参考 Django 迁移、操作数据库。

修改视图函数

当用户请求访问某篇文章时,处理该请求的视图函数为 detail 。一旦该视图函数被调用,说明文章被访问了一次,因此我们修改 detail 视图函数,让被访问的文章在视图函数被调用时阅读量 +1。

blog/views.py

def detail(request, pk):
  post = get_object_or_404(Post, pk=pk)
  
  # 阅读量 +1
  post.increase_views()

  md = markdown.Markdown(extensions=[
    'markdown.extensions.extra',
    'markdown.extensions.codehilite',
    # 记得在顶部引入 TocExtension 和 slugify
    TocExtension(slugify=slugify),
  ])
  post.body = md.convert(post.body)

  m = re.search(r'<div class="toc">\s*<ul>(.*)</ul>\s*</div>', md.toc, re.S)
  post.toc = m.group(1) if m is not None else ''

  return render(request, 'blog/detail.html', context={'post': post})

即只需在视图函数中调用模型的 increase_views 方法即可。

在模板中显示阅读量

在模板中显示阅读量和显示其它字段一样,只需要使用模板变量即可。即模板适当的地方使用 {{ post.views }} 模板变量。这里我们分别修改两个地方,分别是 index.html 和 detail.html。

templates/blog/index.html

<div class="entry-meta">
 ...
 <span class="views-count"><a href="{{ post.get_absolute_url }}" rel="external nofollow" >{{ post.views }} 阅读</a></span>
</div>

templates/blog/detail.html

<div class="entry-meta">
 ...
 <span class="views-count"><a href="#" rel="external nofollow" >{{ post.views }} 阅读</a></span>
</div>

好了,这样当用户每访问一次文章详情,views 记录的数值就会 +1,从而达到粗略统计阅读量的目的。

示例代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
给Python的Django框架下搭建的BLOG添加RSS功能的教程
Apr 08 Python
python实现SMTP邮件发送功能
Jun 16 Python
详解Python如何获取列表(List)的中位数
Aug 12 Python
python 中的divmod数字处理函数浅析
Oct 17 Python
python利用有道翻译实现&quot;语言翻译器&quot;的功能实例
Nov 14 Python
pip install urllib2不能安装的解决方法
Jun 12 Python
Laravel+Dingo/Api 自定义响应的实现
Feb 17 Python
python3实现带多张图片、附件的邮件发送
Aug 10 Python
python如何调用字典的key
May 25 Python
python 判断一组数据是否符合正态分布
Sep 23 Python
Python pathlib模块使用方法及实例解析
Oct 05 Python
python设置 matplotlib 正确显示中文的四种方式
May 10 Python
pygame实现俄罗斯方块游戏(基础篇3)
Oct 29 #Python
python安装gdal的两种方法
Oct 29 #Python
pygame实现俄罗斯方块游戏(基础篇2)
Oct 29 #Python
pygame实现俄罗斯方块游戏(基础篇1)
Oct 29 #Python
pygame实现五子棋游戏
Oct 29 #Python
python多线程案例之多任务copy文件完整实例
Oct 29 #Python
jenkins配置python脚本定时任务过程图解
Oct 29 #Python
You might like
php将远程图片保存到本地服务器的实现代码
2015/08/03 PHP
基于PHP实现通过照片获取ip地址
2016/04/26 PHP
用Javascript实现UTF8编码转换成gb2312编码
2006/12/22 Javascript
新手入门常用代码集锦
2007/01/11 Javascript
用JavaScript玩转游戏物理(一)运动学模拟与粒子系统
2010/06/19 Javascript
Jquery从头学起第四讲 jquery入门教程
2010/08/01 Javascript
基于jquery的给文章加入关键字链接
2010/10/26 Javascript
javascript 学习笔记(八)javascript对象
2011/04/12 Javascript
Extjs4中tree的拖拽功能(可以两棵树之间拖拽) 简单实例
2013/12/08 Javascript
jquery预览图片实现鼠标放上去显示实际大小
2014/01/16 Javascript
JavaScript控制table某列不显示的方法
2015/03/16 Javascript
JQuery控制Radio选中方法分析
2015/05/29 Javascript
js时间查询插件使用详解
2017/04/07 Javascript
element-ui中select组件绑定值改变,触发change事件方法
2018/08/24 Javascript
vue弹窗组件的实现示例代码
2018/09/10 Javascript
Vuex,iView UI面包屑导航使用扩展详解
2019/11/04 Javascript
JS+CSS实现动态时钟
2021/02/19 Javascript
[56:56]VG vs LGD 2019国际邀请赛淘汰赛 胜者组 BO3 第一场 8.22
2019/09/05 DOTA
python基础教程之面向对象的一些概念
2014/08/29 Python
python机器学习之决策树分类详解
2017/12/20 Python
pandas中去除指定字符的实例
2018/05/18 Python
Python实现八皇后问题示例代码
2018/12/09 Python
python区块及区块链的开发详解
2019/07/03 Python
Python基于mediainfo批量重命名图片文件
2020/12/29 Python
jupyter notebook远程访问不了的问题解决方法
2021/01/11 Python
Weblogic和WebSphere不同特点
2012/05/09 面试题
不打扫卫生检讨书
2014/02/12 职场文书
临床医师个人自我评价
2014/04/06 职场文书
大学生个人先进事迹材料范文
2014/05/03 职场文书
2014年班长个人工作总结
2014/11/14 职场文书
物业前台接待岗位职责
2015/04/03 职场文书
《抽屉原理》教学反思
2016/02/20 职场文书
基于Python实现的购物商城管理系统
2021/04/27 Python
golang为什么要统一错误处理
2022/04/03 Golang
Python Numpy库的超详细教程
2022/04/06 Python
MySQL新手入门进阶语句汇总
2022/09/23 MySQL