HelloDjango 第 11 篇:自動生成文章摘要

<p align="center">做者:HelloGitHub-<strong>追夢人物</strong></p>html

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

博客文章的模型有一個 excerpt 字段,這個字段用於存儲文章的摘要。目前爲止,還只能在 django admin 後臺手動爲文章輸入摘要。每次手動輸入摘要比較麻煩,對有些文章來講,只要摘取正文的前 N 個字符做爲摘要,以便提供文章預覽就能夠了。所以咱們來實現若是文章沒有輸入摘要,則自動摘取正文的前 N 個字符做爲摘要,這有兩種實現方法。git

覆寫 save 方法

第一種方法是經過覆寫模型的 save 方法,從正文字段摘取前 N 個字符保存到摘要字段。在 創做後臺開啓,請開始你的表演 中咱們提到過 save 方法中執行的是保存模型實例數據到數據庫的邏輯,所以經過覆寫 save 方法,在保存數據庫前作一些事情,好比填充某個缺失字段的值。github

回顧一下博客文章模型代碼:數據庫

blog/models.py

class Post(models.Model):
    # 其它字段...
    body = models.TextField()
    excerpt = models.CharField(max_length=200, blank=True)
    
    def save(self, *args, **kwargs):
        self.modified_time = timezone.now()
        super().save(*args, **kwargs)

其中 body 字段存儲的是正文,excerpt 字段用於存儲摘要。經過覆寫模型的 save 方法,在數據被保存到數據庫前,先從 body 字段摘取 N 個字符保存到 excerpt 字段中,從而實現自動摘要的目的。具體代碼以下:django

blog/models.py

import markdown
from django.utils.html import strip_tags

class Post(models.Model):
    # 其它字段...
    body = models.TextField()
    excerpt = models.CharField(max_length=200, blank=True)
    
    # 其它方法...
    
    def save(self, *args, **kwargs):
        self.modified_time = timezone.now()

        # 首先實例化一個 Markdown 類,用於渲染 body 的文本。
        # 因爲摘要並不須要生成文章目錄,因此去掉了目錄拓展。
        md = markdown.Markdown(extensions=[
            'markdown.extensions.extra',
            'markdown.extensions.codehilite',
        ])

        # 先將 Markdown 文本渲染成 HTML 文本
        # strip_tags 去掉 HTML 文本的所有 HTML 標籤
        # 從文本摘取前 54 個字符賦給 excerpt
        self.excerpt = strip_tags(md.convert(self.body))[:54]

        super().save(*args, **kwargs)

這裏生成摘要的方案是,先將 body 中的 Markdown 文本轉爲 HTML 文本,去掉 HTML 文本里的 HTML 標籤,而後摘取文本的前 54 個字符做爲摘要。去掉 HTML 標籤的目的是防止前 54 個字符中存在塊級 HTML 標籤而使得摘要格式比較難看。能夠看到不少網站都採用這樣一種生成摘要的方式。markdown

而後在模板中適當的地方使用模板標籤引用 {{ post.excerpt }} 顯示摘要的值便可:函數

templates/blog/index.html

<article class="post post-{{ post.pk }}">
  ...
  <div class="entry-content clearfix">
      <p>{{ post.excerpt }}...</p>
      <div class="read-more cl-effect-14">
          <a href="{{ post.get_absolute_url }}" class="more-link">繼續閱讀 <span class="meta-nav">→</span></a>
      </div>
  </div>
</article>

新添加一篇文章(這樣才能觸發 save 方法,此前添加的文章不會自動生成摘要,要手動保存一下觸發 save 方法),能夠看到摘要效果了。post

使用 truncatechars 模板過濾器

第二種方法是使用 truncatechars 模板過濾器(Filter)。在 django 的模板系統中,模板過濾器的使用語法爲 {{ var | filter: arg }}。能夠將模板過濾看作一個函數,它會做用於被它過濾的模板變量,從而改變模板變量的值。例如這裏的 truncatechars 過濾器能夠截取模板變量值的前 N 個字符顯示。關於模板過濾器,咱們以前使用過 safe 過濾器,能夠參考 讓博客支持 Markdown 語法和代碼高亮 這篇文章中對模板過濾器的說明。網站

例如摘要效果,須要顯示 post.body 的前 54 的字符,那麼能夠在模板中使用 {{ post.body | truncatechars:54 }}

templates/blog/index.html

<article class="post post-{{ post.pk }}">
  ...
  <div class="entry-content clearfix">
      <p>{{ post.body|truncatechars:54 }}</p>
      <div class="read-more cl-effect-14">
          <a href="{{ post.get_absolute_url }}" class="more-link">繼續閱讀 <span class="meta-nav">→</span></a>
      </div>
  </div>
</article>

不過這種方法的一個缺點就是若是前 54 個字符含有塊級 HTML 元素標籤的話(好比一段代碼塊),會使摘要比較難看。因此推薦使用第一種方法。

<p align="center">歡迎關注 HelloGitHub 公衆號,獲取更多開源項目的資料和內容</p>

原文出處:https://www.cnblogs.com/xueweihan/p/11425863.html

相關文章
相關標籤/搜索