【django】對文章的閱讀次數進行記錄與統計,另外數據庫在原來的基礎上加一個Redis。

Python與Web

首發於Python與Web

關注專欄寫文章

 

【記錄】Django學習34

田田田田

田田田田

以後的每一天。

​關注她

對文章的閱讀次數進行記錄與統計,另外數據庫在原來的基礎上加一個Redis。

1、安裝Reids,然後改掉默認端口號。

vim redis.conf
root@Grace:/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(框架)

​贊同​​添加評論

​分享

​收藏

文章被以下專欄收錄

Python與Web

 

Python與Web

主要學習資料:《跟老齊學Python Django實戰》。代碼提交於:https://github.com/tianwei1992/mysite 不對之處請多指教~

關注專欄

推薦閱讀

django框架結構

請求處理的流程客戶端輸入請求(網址)-&gt;-&gt;urls.py通過類名查找到訪問的相應目錄 -&gt;-&gt;調用目錄下的views.py,執行類render方法,告訴django要讀入哪個模板 -&gt;-&gt;查詢到相應…

我相信

關於Django,我想推薦這樣一本書給你

關於Django,我想推薦這樣一本書給你

粥粥發表於汪小汪的數...

揣着Django做項目2:組隊

揣着Django做項目2:組隊

bllli

pyecharts + Flask&Django,該來的總是要來的

pyecharts + Flask&Django,該來的總是要來的

chenjiandongx

還沒有評論

寫下你的評論...

 

 

發佈

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章