基于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中的lambda表达式的用法
Aug 28 Python
python遍历目录的方法小结
Apr 28 Python
Python爬取APP下载链接的实现方法
Sep 30 Python
Python中 传递值 和 传递引用 的区别解析
Feb 22 Python
python 实现对文件夹内的文件排序编号
Apr 12 Python
基于python OpenCV实现动态人脸检测
May 25 Python
python计算日期之间的放假日期
Jun 05 Python
python pandas中对Series数据进行轴向连接的实例
Jun 08 Python
详解pandas如何去掉、过滤数据集中的某些值或者某些行?
May 15 Python
3种python调用其他脚本的方法
Jan 06 Python
Python bytes string相互转换过程解析
Mar 05 Python
Python实现批量将文件复制到新的目录中再修改名称
Apr 12 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 正确解码javascript中通过escape编码后的字符
2010/01/28 PHP
解析PHP中ob_start()函数的用法
2013/06/24 PHP
php mysql_real_escape_string函数用法与实例教程
2013/09/30 PHP
PHP中比较两个字符串找出第一个不同字符位置例子
2014/04/08 PHP
一个基于phpQuery的php通用采集类分享
2014/04/09 PHP
PHP 读取和编写 XML
2014/11/19 PHP
php操作xml入门之cdata区段
2015/01/23 PHP
浅谈PDO的rowCount函数
2015/06/18 PHP
php正则表达式学习笔记
2015/11/13 PHP
图文详解phpstorm配置Xdebug进行调试PHP教程
2016/06/13 PHP
php判断数组是否为空的实例方法
2020/05/10 PHP
JS防止用户多次提交的简单代码
2013/08/01 Javascript
jQuery根据ID获取input、checkbox、radio、select的示例
2014/08/11 Javascript
javascript查询字符串参数的方法
2015/01/28 Javascript
JS往数组中添加项性能分析
2015/02/25 Javascript
js 右侧浮动层效果实现代码(跟随滚动)
2015/11/22 Javascript
js字符串操作总结(必看篇)
2016/11/22 Javascript
JS判断键盘是否按的回车键并触发指定按钮点击操作的方法
2017/02/13 Javascript
jQuery实现select下拉框获取当前选中文本、值、索引
2017/05/08 jQuery
vue.js获取数据库数据实例代码
2017/05/26 Javascript
js学习总结之DOM2兼容处理顺序问题的解决方法
2017/07/27 Javascript
js 提取某()特殊字符串长度的实例
2017/12/06 Javascript
vue路由传参三种基本方式详解
2019/12/09 Javascript
Vue Router 实现动态路由和常见问题及解决方法
2020/03/06 Javascript
Javascript ParentNode和ChildNode接口原理解析
2020/03/16 Javascript
[39:02]DOTA2亚洲邀请赛 3.31 小组赛 B组 Mineski vs VGJ.T
2018/04/01 DOTA
python安装oracle扩展及数据库连接方法
2017/02/21 Python
Python实现的十进制小数与二进制小数相互转换功能
2017/10/12 Python
python里 super类的工作原理详解
2019/06/19 Python
鱼油专家:Omegavia
2016/10/10 全球购物
什么是SCM(软件配置管理)
2014/08/16 面试题
《第一朵杏花》教学反思
2014/04/16 职场文书
2014年前台个人工作总结
2014/11/14 职场文书
财务总监岗位职责范本
2015/04/03 职场文书
费用申请报告范文
2015/05/15 职场文书
2016年大学生党员承诺书
2016/03/24 职场文书