【django】对文章的阅读次数进行记录与统计,另外数据库在原来的基础上加一个Redis。
首发于Python与Web
关注专栏写文章
【记录】Django学习34
以后的每一天。
关注她
对文章的阅读次数进行记录与统计,另外数据库在原来的基础上加一个Redis。
1、安装Reids,然后改掉默认端口号。
vim redis.conf
[email protected]:/opt/redis-5.0.0/src# ./redis-server ../redis.conf #按配置启动
./redis-cli -p port_number
redis虽然是root安装的,所属权也归root,但对其他用户是r-x权限,执行还是没问题的。
2、REDIS相关配置(HOST PORT DB)放settings。
在views.py中引入settings的方法:
from django.conf import settings
注意导入的这个路径并不是物理路径。看看这里怎么回事?
3、在views.py里,首先一次性构造连接对象,然后在视图函数里执行它的方法。
这样,全程只有一个连接对象,但是视图函数的每调用一次就操作一次数据库。
r = redis.StrictRedis(host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=settings.REDIS_DB)
total_views = r.incr("article:{}:views".format(article.id))
每篇文章的浏览次数是redis里面的value,它的key就是"article:{}:views".format(article.id)。
r.incr,用到的是redis字符串类型,如果没有定义,变量的值从从0开始。
redis命令:【笔记】Redis练习
4、至于阅读数的最终呈现,只要变量传进模板就和点赞数的呈现没什么区别:
<span style="margin-left:20px">{{ total_views }}view{{ total_views | pluralize:"s" }}</span>
下面来显示访问最多的文章。
1、这个结果肯定从数据库取:
38 def article_detail(request, id, slug):
39 article = get_object_or_404(ArticlePost, id=id, slug=slug)
40 total_views = r.incr("article:{}:views".format(article.id))
41 r.zincrby("article_ranking", article.id, 1)
42
43 article_ranking = r.zrange("article_ranking", 0, -1, desc=True)[:10]
44 article_ranking_ids = [int(id) for id in article_ranking]
45 most_viewed = list(ArticlePost.objects.filter(id__in=article_ranking_ids))
46 most_viewed.sort(key=lambda x: article_ranking_ids.index(x.id))
47
48 return render(request, "article/list/article_detail.html", {"article": article, "total_views": total_views, "most_viewed": most_viewed})
1)redis五大类型之一是sorted-set,sorted-set中的每一个元素除了本身的值还有score作为排序依据。zincrby就是其中一个方法,用于增加某个元素的socre。
同incr一样,如果这个sorted-set根本不存在……也是可以用的,会算成新建。
[redis中的例子]
zincrby mysset 5 one
这里用一个sorted-set来保存文章的排名情况,其中的元素是article.id,得分自然从0开始,每次有访问(视图函数被调用)就给得分加1。(其实不明白为什么不将就"article:1:views"的取值呢?)
r.zincrby("article_ranking", article.id, 1)
2)article_ranking = r.zrange("article_ranking", 0, -1, desc=True)[:10]
[redis中的例子]
redis 127.0.0.1:6379> zrange mysset 0 -1
1) "one"
2) "two"
3) "three"
4) "four"
desc=True,从"articleranking"这个sorted_set中从大到小取出元素。
3)most_viewed = list(ArticlePost.objects.filter(id__in=article_ranking_ids))
id__in是filter的语法,id在xx区间内。
4)most_viewed.sort(key=lambda x: article_ranking_ids.index(x.id))
是python sort的用法,传入排序依据的关键字,这里是用article.id找到他在article_ranking_ids中的位置,也就是名词作为排序依据。
2、用有序列表<ol>配合for标签展示most_viewed的每一项。
<ol>
{% for article_rank in most_viewed %}
<li>
<a href="{{ article_rank.get_url_path }}">{{ article_rank.title }}</a>
</li>
{% endfor %}
</ol>
article_rank其实就是ArticlePost的实例,所以具有这2个特性。
3、最后回顾一下,取出阅读数最大的十篇文章为什么用到4条语句:
44 article_ranking = r.zrange("article_ranking", 0, -1, desc=True)[:10]
45 article_ranking_ids = [int(id) for id in article_ranking]
46 most_viewed = list(ArticlePost.objects.filter(id__in=article_ranking_ids))
47 most_viewed.sort(key=lambda x: article_ranking_ids.index(x.id))
- 从sorted_set里面取出排名前10的10个对象,列表返回,列表的元素是articleid,而不是article本身
- article_id是str,把str转成int。
- 拿着10个article_id组成的列表筛选出10个article的列表,filter返回的结果又成乱序。
- 对10个article的列表按阅读量重新排序。
[Redis的优点]
- 读取速度快
- 丰富的数据类型
- 操作具有原子性
【之后的思考】
以上是照着书上做的,感觉书上这么操作应该是为了练习使用Redis,否则是有更简单的实现方法。
比如这里就想增加文章的浏览数,那么大可以在ArticlePost里面加一个字段比如viewcount,然后显示和修改这个变量就行,找出top10浏览量文章也可以把所有文章取出来用sort排序,取key=view_count就行。
但这篇文章的实现脱离了原来的dblite,把每个文章的浏览量作为一个字符串类型的数据存储在redis里面;为了找出top10浏览量的文章,在redis里面又另外开辟了一个sorted-set,其中的元素就是article_id,元素的score表示浏览量。 这样浏览量其实被保存了两次,在我看来是冗余的,不知道为什么要这样。
编辑于 2018-10-20
赞同添加评论
分享
收藏
文章被以下专栏收录
主要学习资料:《跟老齐学Python Django实战》。代码提交于:https://github.com/tianwei1992/mysite 不对之处请多指教~
关注专栏
推荐阅读
django框架结构
关于Django,我想推荐这样一本书给你
揣着Django做项目2:组队
pyecharts + Flask&Django,该来的总是要来的
还没有评论
写下你的评论...
发布