统计文章阅读量

2017-05-1729967 阅读18 评论

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

增加新字段

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

blog/models.py

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

注意 views 字段的类型为 PositiveIntegerField,该类型的值只允许为正整数或 0,因为阅读量不可能为负值。初始化时 views 的值为 0。

增加模型方法

一旦用户访问了某篇文章,这时就应该将 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 将更改反应到数据库中。激活虚拟环境,运行如下两条命令:

python manage.py makemigrations
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()

    post.body = markdown.markdown(post.body,
                                  extensions=[
                                      'markdown.extensions.extra',
                                      'markdown.extensions.codehilite',
                                      'markdown.extensions.toc',
                                  ])
    form = CommentForm()
    comment_list = post.comment_set.all()
    context = {'post': post,
               'form': form,
               'comment_list': comment_list
               }
    return render(request, 'blog/detail.html', context=context)

即只需在视图函数中调用模型的 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 }}">{{ post.views }} 阅读</a></span>
</div>
templates/blog/detail.html

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

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

总结

本章节的代码位于:Step16: record post views

如果遇到问题,请通过下面的方式寻求帮助。

-- EOF --

18 评论
登录后回复
诗酒止步lp
2019-08-05 18:31:50

请问,阅读量+1 怎么防止一个用户不停刷新一直+1 怎么设置时间控制

回复
Wenvki 诗酒止步lp
2020-03-20 09:31:57

user_agent+ip+cookie自动过期

回复
二涛被占用了
2018-10-10 21:54:39

回复
Jerot-China
2018-06-18 23:29:15

博主,我照着你的样子 在本地是有阅读量的,但是更新到线上之后就没有阅读量了。看了下应该是数据库没同步过去。我makemigrations 和 migrate都执行了。现在也找不到什么原因了

回复
真实的-smile Jerot-China
2018-12-23 12:32:53

朋友你解决没?

回复
Pengyi Jerot-China
2019-01-04 11:31:49

只会同步表结构过去,数据是不会过去的

回复
Xia911227
2018-03-22 19:32:22

123123

回复
y正在输入
2018-03-16 12:51:15

博主你好,这个博客系统没有登录注册注销的功能吗

回复
追梦人物 y正在输入
2018-04-02 16:48:29

目前没有注销,登录我希望大家使用第三方账户登录。

回复
用户6452171002
2018-02-12 10:42:34

感谢博主

回复
happpygc
2017-09-19 19:36:59

Image

回复
老山龙先生
2017-05-27 11:50:31

大大你好,问个问题,博客首页每篇文章的评论数,您的实现思路是怎么样的。

回复
DawnOct 老山龙先生
2017-06-13 17:55:53

{{post.comment_set.count}}

回复
ghosx 老山龙先生
2017-07-15 20:03:15

{{comment_list.count}}

回复
吉超 老山龙先生
2018-01-02 11:09:21

comment_list|length

回复
吉超 吉超
2018-01-02 11:09:41

{{ comment_list|length }}

回复
量飞 吉超
2018-01-06 20:11:15

和 {{comment_list.count}} 有什么区别呢?

回复
Wenvki 老山龙先生
2020-03-20 09:34:37

最好是在Post模型新增一个整数字段,每次评论/删除评论加减1.
因为这个字段属于频繁查询的字段,这样做能一次性从Post模型获取到你要的结果。

回复