【django】对文章的阅读次数进行记录与统计,另外数据库在原来的基础上加一个Redis。

【django】对文章的阅读次数进行记录与统计,另外数据库在原来的基础上加一个Redis。

首发于Python与Web

关注专栏写文章

 

【记录】Django学习34

【django】对文章的阅读次数进行记录与统计,另外数据库在原来的基础上加一个Redis。

田田田田

以后的每一天。

​关注她

对文章的阅读次数进行记录与统计,另外数据库在原来的基础上加一个Redis。

【django】对文章的阅读次数进行记录与统计,另外数据库在原来的基础上加一个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))
  1. 从sorted_set里面取出排名前10的10个对象,列表返回,列表的元素是articleid,而不是article本身
  2. article_id是str,把str转成int。
  3. 拿着10个article_id组成的列表筛选出10个article的列表,filter返回的结果又成乱序。
  4. 对10个article的列表按阅读量重新排序。

[Redis的优点]

  1. 读取速度快
  2. 丰富的数据类型
  3. 操作具有原子性

 

 

【之后的思考】

以上是照着书上做的,感觉书上这么操作应该是为了练习使用Redis,否则是有更简单的实现方法。

比如这里就想增加文章的浏览数,那么大可以在ArticlePost里面加一个字段比如viewcount,然后显示和修改这个变量就行,找出top10浏览量文章也可以把所有文章取出来用sort排序,取key=view_count就行。

 

但这篇文章的实现脱离了原来的dblite,把每个文章的浏览量作为一个字符串类型的数据存储在redis里面;为了找出top10浏览量的文章,在redis里面又另外开辟了一个sorted-set,其中的元素就是article_id,元素的score表示浏览量。 这样浏览量其实被保存了两次,在我看来是冗余的,不知道为什么要这样。

 

 

 

 

编辑于 2018-10-20

Django(框架)

​赞同​​添加评论

​分享

​收藏

文章被以下专栏收录

【django】对文章的阅读次数进行记录与统计,另外数据库在原来的基础上加一个Redis。

 

Python与Web

主要学习资料:《跟老齐学Python Django实战》。代码提交于:https://github.com/tianwei1992/mysite 不对之处请多指教~

关注专栏

推荐阅读

django框架结构

请求处理的流程客户端输入请求(网址)-&gt;-&gt;urls.py通过类名查找到访问的相应目录 -&gt;-&gt;调用目录下的views.py,执行类render方法,告诉django要读入哪个模板 -&gt;-&gt;查询到相应…

我相信

【django】对文章的阅读次数进行记录与统计,另外数据库在原来的基础上加一个Redis。

关于Django,我想推荐这样一本书给你

粥粥发表于汪小汪的数...

【django】对文章的阅读次数进行记录与统计,另外数据库在原来的基础上加一个Redis。

揣着Django做项目2:组队

bllli

【django】对文章的阅读次数进行记录与统计,另外数据库在原来的基础上加一个Redis。

pyecharts + Flask&Django,该来的总是要来的

chenjiandongx

还没有评论

写下你的评论...

 

 

发布