如何精确地记录一篇文章的阅读量是一个比较复杂的问题,不过对于我们的博客来说,没有必要记录的那么精确。因此我们使用一种简单但有效的方式来记录博客文章的阅读量:文章每被浏览一次,则其阅读量 +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。
如果遇到问题,请通过下面的方式寻求帮助。
- 在下方评论区留言。
- 将问题的详细描述通过邮件发送到 djangostudyteam@163.com,一般会在 24 小时内回复。
- 在 Pythonzhcn 社区的新手问答版块 发布帖子。
-- EOF --
请问,阅读量+1 怎么防止一个用户不停刷新一直+1 怎么设置时间控制
user_agent+ip+cookie自动过期
的
博主,我照着你的样子 在本地是有阅读量的,但是更新到线上之后就没有阅读量了。看了下应该是数据库没同步过去。我makemigrations 和 migrate都执行了。现在也找不到什么原因了
朋友你解决没?
只会同步表结构过去,数据是不会过去的
123123
博主你好,这个博客系统没有登录注册注销的功能吗
目前没有注销,登录我希望大家使用第三方账户登录。
感谢博主
大大你好,问个问题,博客首页每篇文章的评论数,您的实现思路是怎么样的。
{{post.comment_set.count}}
{{comment_list.count}}
comment_list|length
{{ comment_list|length }}
和 {{comment_list.count}} 有什么区别呢?
最好是在Post模型新增一个整数字段,每次评论/删除评论加减1.
因为这个字段属于频繁查询的字段,这样做能一次性从Post模型获取到你要的结果。