Diango博客--6.Markdown 文章自动生成目录
文章目錄
- 0.思路引導(dǎo)
- 1.在文中插入目錄
- 2.在頁(yè)面的任何地方插入目錄
- 3.美化標(biāo)題的錨點(diǎn) URL
0.思路引導(dǎo)
Markdown 在解析內(nèi)容的同時(shí)還可以自動(dòng)提取整個(gè)內(nèi)容的目錄結(jié)構(gòu),本文內(nèi)容將從以下幾個(gè)方面展開:
1)在文中插入目錄;
2)在頁(yè)面的任何地方插入目錄;
3)美化標(biāo)題的錨點(diǎn) URL。
1.在文中插入目錄
博客的 Post(文章)模型,其中 body 是我們存儲(chǔ) Markdown 文本的字段:
文件位置:blog/models.py
from django.db import modelsclass Post(models.Model):# Other fields ...body = models.TextField()再來回顧一下文章詳情頁(yè)的視圖,我們?cè)?detail 視圖函數(shù)中將 post 的 body 字段中的 Markdown 文本解析成了 HTML 文本,然后傳遞給模板顯示
文件位置:blog/views.py
markdown.markdown() 方法把 post.body 中的 Markdown 文本解析成了 HTML 文本。同時(shí)我們還給該方法提供了一個(gè) extensions 的額外參數(shù)。其中 markdown.extensions.toc 就是自動(dòng)生成目錄的拓展。
在渲染 Markdown 文本時(shí)加入了 toc 拓展后,就可以在文中插入目錄了。方法是在書寫 Markdown 文本時(shí),在你想生成目錄的地方插入 [TOC] 標(biāo)記即可。
后臺(tái)輸入如下:
效果展示如下:
2.在頁(yè)面的任何地方插入目錄
上述方式的一個(gè)局限性就是只能通過 [TOC] 標(biāo)記在文章內(nèi)容中插入目錄。如果想在頁(yè)面的其它地方,比如側(cè)邊欄插入一個(gè)目錄該怎么做呢?只需要稍微改動(dòng)一下解析 Markdown 文本內(nèi)容的方式即可。
以detail.py中的模板標(biāo)簽{% block toc %}為例,其渲染的位置位于詳情頁(yè)的側(cè)邊欄,現(xiàn)在想要在側(cè)邊欄中生成目錄。
{% block toc %} ... {% endblock toc %}需要修改的代碼如下:
文件位置:blog/views.py
def detail(request, pk):post = get_object_or_404(Post, pk=pk)md = markdown.Markdown(extensions=['markdown.extensions.extra','markdown.extensions.codehilite','markdown.extensions.toc',])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})文件位置:detail.html
{% block toc %}{% if post.toc %}<div class="widget widget-content"><h3 class="widget-title">文章目錄</h3><div class="toc"><ul>{{ post.toc|safe }}</ul></div></div>{% endif %} {% endblock toc %}在這里,我們沒有直接用 markdown.markdown() 方法來渲染 post.body 中的內(nèi)容,而是先實(shí)例化了一個(gè) markdown.Markdown 對(duì)象 md,和 markdown.markdown() 方法一樣,也傳入了 extensions 參數(shù)。
接著我們便使用該實(shí)例的 convert 方法將 post.body 中的 Markdown 文本解析成 HTML 文本。而一旦調(diào)用該方法后,實(shí)例 md 就會(huì)多出一個(gè) toc 屬性,這個(gè)屬性的值就是內(nèi)容的目錄,我們把 md.toc 的值通過整個(gè)表達(dá)式的處理,賦給 post.toc 。
注意:為了防止文章目錄為空的情況,使用正則表達(dá)式來測(cè)試 ul 標(biāo)簽中是否包裹有元素,從而來確定是否存在目錄。并使用新的模板標(biāo)簽 {% if %},來對(duì)post.toc做條件判斷。
效果展示如下:
3.美化標(biāo)題的錨點(diǎn) URL
文章內(nèi)容的標(biāo)題被設(shè)置了錨點(diǎn),點(diǎn)擊目錄中的某個(gè)標(biāo)題,頁(yè)面就會(huì)跳到該文章內(nèi)容中標(biāo)題所在的位置,這時(shí)候?yàn)g覽器的 URL 顯示的值可能不太美觀,比如像下面的樣子:
#1_1 就是錨點(diǎn),Markdown 在設(shè)置錨點(diǎn)時(shí)利用的是標(biāo)題的值,由于通常我們的標(biāo)題都是中文,Markdown 沒法處理,所以它就忽略的標(biāo)題的值,而是簡(jiǎn)單地在后面加了個(gè)1 _1 這樣的錨點(diǎn)值。為了解決這一個(gè)問題,需要修改一下傳給 extentions 的參數(shù),其具體做法如下:
文件位置:blog/views.py
from django.utils.text import slugify from markdown.extensions.toc import TocExtensiondef detail(request, pk):post = get_object_or_404(Post, pk=pk)md = markdown.Markdown(extensions=['markdown.extensions.extra','markdown.extensions.codehilite',# 記得在頂部引入 TocExtension 和 slugifyTocExtension(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})和之前不同的是,extensions 中的 toc 拓展不再是字符串 markdown.extensions.toc ,而是 TocExtension 的實(shí)例。
TocExtension 在實(shí)例化時(shí)其 slugify 參數(shù)可以接受一個(gè)函數(shù),這個(gè)函數(shù)將被用于處理標(biāo)題的錨點(diǎn)值。
Markdown 內(nèi)置的處理方法不能處理中文標(biāo)題,所以我們使用了 django.utils.text 中的 slugify 方法,該方法可以很好地處理中文。
效果展示如下:
總結(jié)
以上是生活随笔為你收集整理的Diango博客--6.Markdown 文章自动生成目录的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 解决ubuntu首次安装Mysql之后,
- 下一篇: 大学计算机word操作教程,word技巧