Django部落格使用Markdown自動生成目錄

ConnorK發表於2021-03-07

Django 開發部落格使用 Markdown 來為文章提供排版支援。Markdown 在渲染內容的同時還可以自動提取整個內容的目錄結構,本文將教你如何使用 Markdown 來為文章自動生成目錄。

博文模型

例如建立的博文模型如下:


class Post(models.Model):
    # Other fields ...
    body = models.TextField()

檢視函式

在博文詳情檢視函式中使用Markdown擴充套件為 post 新增目錄屬性,如下:

import markdown
from django.shortcuts import render, get_object_or_404

def detail(request, pk):
    post = get_object_or_404(Post, pk=pk)
    post.body = markdown.markdown(post.body,
                                  extensions=[
                                      'markdown.extensions.extra',
                                      'markdown.extensions.codehilite',
                                      'markdown.extensions.toc',  # 目錄擴充套件
                                  ])
    return render(request, 'blog/detail.html', {'post': post})

HTML中渲染目錄

<div>
    {{ post.toc|safe }}
</div>

美化標題錨點

文章內容的標題被設定了錨點,點選目錄中的某個標題,頁面就會跳到該文章內容中標題所在的位置,這時候瀏覽器的 URL 顯示的值可能不太美觀,比如像下面的樣子:

127.0.0.1:8000/post/8/#_1

127.0.0.1:8000/post/8/#_3

#_1 就是錨點,Markdown 在設定錨點時利用的是標題的值,由於通常我們的標題都是中文,Markdown 沒法處理,所以它就忽略的標題的值,而是簡單地在後面加了個 _1 這樣的錨點值。
為了解決這一個問題,我們需要修改一下傳給 extentions 的引數,其具體做法如下:

import markdown
from django.shortcuts import render, get_object_or_404

from django.utils.text import slugify
from markdown.extensions.toc import TocExtension

def detail(request, pk):
    post = get_object_or_404(Post, pk=pk)
    md = markdown.Markdown(extensions=[
        'markdown.extensions.extra',
        'markdown.extensions.codehilite',
        TocExtension(slugify=slugify),
    ])
    post.body = md.convert(post.body)
    return render(request, 'blog/detail.html', {'post': post, 'toc': md.toc})

和上一節不同的是,extensions 中的 toc 擴充不再是字串 markdown.extensions.toc ,而是 TocExtension 的例項。TocExtension 在例項化時其 slugify 引數可以接受一個函式作為引數,這個函式將被用於處理標題的錨點值。Markdown 內建的處理方法不能處理中文標題,所以我們使用了 django.utils.text 中的 slugify 方法,該方法可以很好地處理中文。
這時候標題的錨點 URL 變得好看多了。

http://127.0.0.1:8000/post/8/#我是標題一

http://127.0.0.1:8000/post/8/#我是標題二

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章