開發 Django 部落格文章閱讀量統計功能

  • 2019 年 10 月 18 日
  • 筆記

作者:HelloGitHub-追夢人物

文中所涉及的示例程式碼,已同步更新到 HelloGitHub-Team 倉庫

如何精確地記錄一篇文章的閱讀量是一個比較複雜的問題,不過對於我們的部落格來說,沒有必要記錄的那麼精確。因此我們使用一種簡單但有效的方式來記錄部落格文章的閱讀量:文章每被瀏覽一次,則其閱讀量 +1,即所謂的文章頁面 PV(Page View)數。雖然簡單粗暴,但卻高效實用。

增加新欄位

為了記錄文章的瀏覽量,需要在文章的資料庫表中新增一個用於存儲閱讀量的欄位。因此給部落格文章的模型新增一個 views 欄位:

blog/models.py    class Post(models.Model):      # ... 其它已有欄位      # 新增 views 欄位記錄閱讀量      views = models.PositiveIntegerField(default=0, editable=False)

注意 views 欄位的類型為 PositiveIntegerField,該類型的值只允許為正整數或 0,因為閱讀量不可能為負值。初始化時 views 的值為 0。將 editable 參數設為 False 將不允許通過 django admin 後台編輯此欄位的內容。因為閱讀量應該根據被訪問次數統計,而不應該人為修改。

增加模型方法

一旦用戶訪問了某篇文章,這時就應該將 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 將更改反應到資料庫中。在項目根目錄運行如下兩條命令:

$ pipenv run python manage.py makemigrations  $ pipenv run 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()        md = markdown.Markdown(extensions=[          'markdown.extensions.extra',          'markdown.extensions.codehilite',          # 記得在頂部引入 TocExtension 和 slugify          TocExtension(slugify=slugify),      ])      post.body = md.convert(post.body)        m = re.search(r'<div class="toc">s*<ul>(.*)</ul>s*</div>', md.toc, re.S)      post.toc = m.group(1) if m is not None else ''        return render(request, 'blog/detail.html', context={'post': post})

即只需在視圖函數中調用模型的 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,從而達到粗略統計閱讀量的目的。


『講解開源項目系列』——讓對開源項目感興趣的人不再畏懼、讓開源項目的發起者不再孤單。跟著我們的文章,你會發現編程的樂趣、使用和發現參與開源項目如此簡單。歡迎留言聯繫我們、加入我們,讓更多人愛上開源、貢獻開源~