基于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内置的字符串处理函数整理
Jan 29 Python
python的re模块应用实例
Sep 26 Python
python进程管理工具supervisor的安装与使用教程
Sep 05 Python
Python使用django框架实现多人在线匿名聊天的小程序
Nov 29 Python
详解Python中 sys.argv[]的用法简明解释
Dec 20 Python
python3 写一个WAV音频文件播放器的代码
Sep 27 Python
Django实现CAS+OAuth2的方法示例
Oct 30 Python
关于Tensorflow分布式并行策略
Feb 03 Python
python3使用Pillow、tesseract-ocr与pytesseract模块的图片识别的方法
Feb 26 Python
python实现的人脸识别打卡系统
May 08 Python
pytorch 实现多个Dataloader同时训练
May 29 Python
Python中生成随机数据安全性、多功能性、用途和速度方面进行比较
Apr 14 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和MySql来与ODBC数据连接
2006/10/09 PHP
php一些错误处理的方法与技巧总结
2013/08/10 PHP
PHP线程的内存回收问题
2016/07/08 PHP
PHP 文件锁与进程锁的使用示例
2017/08/07 PHP
javascript 循环读取JSON数据的代码
2010/07/17 Javascript
in.js 一个轻量级的JavaScript颗粒化模块加载和依赖关系管理解决方案
2011/07/26 Javascript
JQuery记住用户名和密码的具体实现
2014/04/04 Javascript
javascript在网页中实现读取剪贴板粘贴截图功能
2014/06/07 Javascript
bootstrap改变按钮加载状态
2014/12/01 Javascript
jQuery大于号(&gt;)选择器的作用解释
2015/01/13 Javascript
JS自定义对象实现Java中Map对象功能的方法
2015/01/20 Javascript
在Node.js应用中读写Redis数据库的简单方法
2015/06/30 Javascript
Angular ng-class详解及实例代码
2016/09/19 Javascript
Javascript 闭包详解及实例代码
2016/11/30 Javascript
JavaScript轻松创建级联函数的方法示例
2017/02/10 Javascript
vue不通过路由直接获取url中参数的方法示例
2017/08/24 Javascript
JS实现单张或多张图片持续无缝滚动的示例代码
2020/05/10 Javascript
[42:20]Secret vs Liquid 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
[38:23]完美世界DOTA2联赛循环赛 FTD vs PXG BO2第二场 11.01
2020/11/02 DOTA
python获取糗百图片代码实例
2013/12/18 Python
python的Template使用指南
2014/09/11 Python
python修改字典内key对应值的方法
2015/07/11 Python
Python图像处理之简单画板实现方法示例
2018/08/30 Python
Python判断一个三位数是否为水仙花数的示例
2018/11/13 Python
pytorch进行上采样的种类实例
2020/02/18 Python
在Keras中利用np.random.shuffle()打乱数据集实例
2020/06/15 Python
python中的django是做什么的
2020/07/31 Python
html5教程制作简单画板代码分享
2013/12/04 HTML / CSS
西班牙用户之间买卖视频游戏的平台:Wakkap
2020/03/21 全球购物
医学专业个人求职自荐信格式
2013/09/23 职场文书
运动会广播稿150字
2014/02/19 职场文书
离婚协议书范本
2015/01/26 职场文书
党务工作者主要事迹材料
2015/11/03 职场文书
小学六一儿童节活动开幕词
2016/03/04 职场文书
nginx安装以及配置的详细过程记录
2021/09/15 Servers
详解 TypeScript 枚举类型
2021/11/02 Javascript