文章目錄
- 0.思路引導
- 1.方法一:覆寫 save 方法
- 2.方法二:使用 truncatechars 模板過濾器
0.思路引導
博客文章的模型有一個 excerpt 字段,這個字段用于存儲文章的摘要。
若在 django admin 后臺手動為文章輸入摘要,每次手動輸入摘要比較麻煩。
若想要程序自動摘取正文的前 N 個字符作為摘要,以便提供文章預覽就可以了。
因此我們來實現如果文章沒有輸入摘要,則自動摘取正文的前 N 個字符作為摘要。
1.方法一:覆寫 save 方法
第一種方法是通過覆寫模型的 save()方法,從正文body 中摘取前 N 個字符保存到摘要字段。
save()方法中執行的是保存模型實例數據到數據庫的邏輯,因此通過覆寫 save() 方法,在保存數據庫前做一些事情,比如填充某個缺失字段的值。
方案:先將 body 中的 Markdown 文本轉為 HTML 文本,去掉 HTML 文本里的 HTML 標簽,然后摘取文本的前 54 個字符作為摘要。去掉 HTML 標簽的目的是防止前 54 個字符中存在塊級 HTML 標簽而使得摘要格式比較難看。可以看到很多網站都采用這樣一種生成摘要的方式。
代碼位置:blog/models.py
import markdown
from django.utils.html import strip_tagsclass 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 個字符賦給 excerptself.excerpt = strip_tags(md.convert(self.body))[:54]super().save(*args, **kwargs)
然后在模板中適當的地方使用模板標簽引用 {{ 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 方法),可以看到摘要效果如下:
2.方法二:使用 truncatechars 模板過濾器
在 django 的模板系統中,我們之前使用過 safe 過濾器,使用語法為 {{ var | filter: arg }}。可以將模板過濾看做一個函數,它會作用于被它過濾的模板變量,從而改變模板變量的值。
第二種方法是使用 truncatechars 模板過濾器(Filter),其可以截取模板變量值的前 N 個字符顯示。
例如摘要效果,需要顯示 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 元素標簽的話(比如一段代碼塊),會使摘要比較難看。所以推薦使用第一種方法。