文章瀏覽量是所有社交類網站所必備的數據,足以顯示其重要性了。
博主可以通過瀏覽量來評估某篇文章的受歡迎程度,讀者也能夠通過瀏覽量來篩選質量更高的文章。
然而,準確統計瀏覽量並不簡單:
- 某些類型的請求不應該統計爲瀏覽量,比如作者自己的瀏覽或編輯文章之後的重定向請求;
- 由於用戶衆多,瀏覽量的數據時刻都在快速更新,會給數據庫帶來很大的壓力。因此很多大型網站都會使用如Redis這樣的讀寫速度非常快的內存數據庫輔助存儲。
因爲我們的項目是博客網站,粗略統計就可以了,也沒有那麼大的用戶壓力,所以設計就簡單得多了。
模型
瀏覽量作爲每篇博文都有的數據,需要一個字段來存儲。
因此修改文章的模型:
article/models.py
...
class ArticlePost(models.Model):
...
total_views = models.PositiveIntegerField(default=0)
...
PositiveIntegerField
是用於存儲正整數的字段default=0
設定初始值從0開始
修改完數據庫別忘了要數據遷移,否則更改不會生效。
由於新字段設置了初始值,遷移會很順暢:
(env) E:\django_project\my_blog>python manage.py makemigrations
Migrations for 'article':
article\migrations\0003_articlepost_total_views.py
- Add field total_views to articlepost
Migrations for 'userprofile':
userprofile\migrations\0002_auto_20181227_2041.py
- Alter field avatar on profile
- Alter field user on profile
(env) E:\django_project\my_blog>python manage.py migrate
Operations to perform:
Apply all migrations: admin, article, auth, contenttypes, sessions, userprofile
Running migrations:
Applying article.0003_articlepost_total_views... OK
Applying userprofile.0002_auto_20181227_2041... OK
列表模板
爲了方便觀察效果,這次先寫模板文件。
什麼地方需要顯示瀏覽量呢?很容易想到的就是文章列表了。修改文章列表的模板:
templates/article/list.html
...
<div class="card-footer">
<!-- 已有代碼 -->
<a href="{% url 'article:article_detail' article.id %}"
class="btn btn-primary">
閱讀本文
</a>
<!-- 顯示瀏覽量 -->
<span>
<small class="col align-self-end" style="color: gray;">
瀏覽: {{ article.total_views }}
</small>
</span>
</div>
...
筆者將瀏覽量顯示在了**“閱讀本文”**的邊上。
有的同學覺得顯示在這裏不好看,請修改代碼,將其放到自己最滿意的地方。(順便熟悉一下Bootstrap!)
詳情模板
除了文章列表外,通常詳情頁面中也需要顯示瀏覽量。
除此之外,在前面的學習中爲了方便,沒有做任何權限管理,以至於任何用戶都可以對所有文章進行修改、刪除:
這樣是肯定不行的,必須修復這個嚴重的錯誤。
修改article/detail.html
模板文件:
templates/article/detail.html
...
<!-- 文章詳情 -->
<div class="container">
<div class="row">
...
<div class="col-12 alert alert-success">
<div>
作者:{{ article.author }}
{% if user == article.author %}
· <a href="#" onclick="confirm_delete()">刪除文章</a>
· <a href="{% url "article:article_update" article.id %}">
編輯文章
</a>
{% endif %}
</div>
<div>
瀏覽:{{ article.total_views }}
</div>
</div>
...
</div>
...
修改內容有:
- 確認當前登錄用戶是文章的作者,才顯示“刪除文章、“編輯文章”兩個鏈接
- 顯示瀏覽量
修改後的頁面如下:
上圖中由於文章作者和登錄用戶不一致,修改文章的鏈接沒有渲染出來了;如果登錄用戶是作者本人,它們又會正常顯示。
這樣的方法可以阻止大部分的“好用戶”非法修改數據。但是如果有“壞用戶”直接輸入url地址來使壞,該怎麼辦呢?所以光是靠前端頁面來鑑權是不夠的。
視圖
現在瀏覽量能夠正確顯示了,但是由於沒有進行任何處理,其數值會一直爲0。我們希望每當用戶訪問詳情頁面時,瀏覽量就加1。
修改article_detail()
如下:
article/views.py
...
def article_detail(request, id):
article = ArticlePost.objects.get(id=id)
# 瀏覽量 +1
article.total_views += 1
article.save(update_fields=['total_views'])
...
update_fields=[]
指定了數據庫只更新total_views
字段,優化執行效率。
測試一下,可以正常對瀏覽量計數了:
視圖中鑑權
前面講了,光是在模板中鑑權是不夠的,必須在後端業務邏輯中再次驗證用戶身份。
修改article_update()
更新文章的視圖:
article/views.py
...
# 提醒用戶登錄
@login_required(login_url='/userprofile/login/')
def article_update(request, id):
# 已有代碼
article = ArticlePost.objects.get(id=id)
# 過濾非作者的用戶
if request.user != article.author:
return HttpResponse("抱歉,你無權修改這篇文章。")
...
視圖中進行了兩次鑑權:
login_required
裝飾器過濾未登錄的用戶if
語句過濾已登錄、但非作者本人的用戶
通過在業務邏輯中再次驗證身份,完全阻止惡意用戶從中使壞了。
除了更新文章的視圖外,刪除文章也應該做類似的工作,請讀者自行修改並測試。
總結
本章完成了簡單的統計瀏覽量的功能,並且在前後端中對用戶的身份進行了驗證。
下一章學習與瀏覽量緊密相關的功能:查詢最熱文章。
- 有疑問請在杜賽的個人網站留言,我會盡快回復。
- 或Email私信我:[email protected]
- 項目完整代碼:Django_blog_tutorial
轉載請註明出處。