Django搭建个人博客:渲染Markdown文章目录

1759阅读 · 21评论 · 2019/01/01发布   前往评论

对会读书的人来说,读一本书要做的第一件事,就是仔细阅读这本书的目录。阅读目录可以对整体内容有所了解,并清楚地知道感兴趣的部分在哪里,提高阅读质量。

博文也是同样的,好的目录对博主和读者都很有帮助。更进一步的是,还可以在目录中设置锚点,点击标题就立即前往该处,非常的方便。

文中的目录

之前我们已经为博文支持了Markdown语法,现在继续增强其功能。

有折腾代码高亮的痛苦经历之后,设置Markdown的目录扩展就显得特别轻松了。

修改文章详情视图:

article/views.py

...

# 文章详情
def article_detail(request, id):
    ...
    article.body = markdown.markdown(article.body,
        extensions=[
        'markdown.extensions.extra',
        'markdown.extensions.codehilite',

        # 目录扩展
        'markdown.extensions.TOC',
        ]
    )
    ...

仅仅是将将markdown.extensions.TOC扩展添加了进去。

TOC: Table of Contents,即目录的意思

代码增加这一行就足够了。为了方便测试,往之前的文章中添加几个一级标题、二级标题等。

还记得Markdown语法如何写标题吗?一级标题:# title1,二级标题:## title2

然后你可以在文中的任何地方插入[TOC]字符串,目录就自动生成好了:

点击标题,页面就立即前往相应的标题处(即“锚点”的概念)。

任意位置的目录

上面的方法只能将目录插入到文章当中。如果我想把目录插入到页面的任何一个位置呢?

也简单,这次需要修改Markdown的渲染方法:

article/views.py

...

def article_detail(request, id):
    ...

    # 修改 Markdown 语法渲染
    md = markdown.Markdown(
        extensions=[
        'markdown.extensions.extra',
        'markdown.extensions.codehilite',
        'markdown.extensions.toc',
        ]
    )
    article.body = md.convert(article.body)

    # 新增了md.toc对象
    context = { 'article': article, 'toc': md.toc }

    return render(request, 'article/detail.html', context)

为了能将toc单独提取出来,我们先将Markdown类赋值给一个临时变量md,然后用convert()方法将正文渲染为html页面。通过md.toc将目录传递给模板。

注意markdown.markdown()markdown.Markdown()的区别

更详细的解释见:官方文档

为了将新的目录渲染到页面中,需要修改文章详情模板:

templates/article/detail.html

...

<div class="container">
    <div class="row">
        <!-- 将原有内容嵌套进新的div中 -->
        <div class="col-9">
            <h1 class="mt-4 mb-4">{{ article.title }}</h1>
            <div class="alert alert-success">
                ...
            </div>
        </div>

        <!-- 新增的目录 -->
        <div class="col-3 mt-4">
            <h4><strong>目录</strong></h4>
            <hr>
            <div>
                {{ toc|safe }}
            </div>
        </div>
    </div>
</div>

...
  • 重新布局,将原有内容装进col-9的容器中,将右侧col-3的空间留给目录
  • toc需要|safe标签才能正确渲染

重新打开页面:

总结

完成了文章的目录功能,至此文章详情页面也比较完善了。





<< 搜索文章 发表评论 >>
本文作者: 杜赛
发布时间: 2019年01月01日 - 15:06
最后更新: 2019年01月28日 - 21:29
知识共享许可协议   转载请保留原文链接及作者

登录 后回复

共有21条评论

avatar
只能这样啦 么么哒! 1

在手机端能上传图片?

6个月前 回复


avatar
杜赛 [博主] 只能这样啦 么么哒! 1

手机上传图片?啥意思

6个月前 回复


avatar
只能这样啦 杜赛 [博主] 么么哒! 1

用手机发博文,博文中包含图片

6个月前 回复


avatar
杜赛 [博主] 只能这样啦 么么哒! 1

Markdown中的图片实际上只是一个url而已,用手机写一样的。

上传图片的话需要另外写代码,我准备后面讲的

6个月前 回复


avatar
只能这样啦 杜赛 [博主] 么么哒! 1

ok .我慢慢等。

6个月前 回复


avatar
17647361832 么么哒! 2

请问如果想让代码显示每一行的行数应该怎么写呢,网上没有找到相关的说明

5个月前 回复


avatar
杜赛 [博主] 17647361832 么么哒! 1

python-markdown默认是不显示行号的。

想显示行号需要向高亮扩展中传入参数:

# Moarkdown 语法渲染
md = markdown.Markdown(
    extensions=[
    ...

    # 语法高亮扩展
    'markdown.extensions.codehilite(linenums=True)',

    ...
)

默认的样式是白色主题;并且由于代码块会被包裹到table中去,有可能样式看起来不太好看(特别是深色主题)。

想修改样式也可以,直接在css中改就行了。因为代码高亮本质上就是css样式的应用。

5个月前 回复


avatar
流天 杜赛 [博主] 么么哒! 1

我这边加入linenums=True出现语法错误。看源码

试试其他也用。网上其他地方都没有说明,也试了元祖或者列表的方式还是不行。

不知该咋办?

3个月前 回复


avatar
杜赛 [博主] 流天 么么哒! 1

你用的是Markdown类吧?

注意是markdown.Markdown,不是markdown.markdown

或者把库换成教程相同的版本,写个小脚本测试一下。

3个月前 回复


avatar
流天 杜赛 [博主] 么么哒! 1

3个月前 回复


avatar
wangfanazz 么么哒! 2

我想问一下这个文章目录怎么才能一直在右边显示,而不是随着文章的滚动目录也就上去了?

4个月前 回复


avatar
杜赛 [博主] wangfanazz 么么哒! 1

GitHub上有一个开源js插件,叫sticky sidebar,您找找看

4个月前 回复


avatar
stormsha 么么哒! 1

看到博主的炫酷评论区,也给自己的站点加了炫酷的特效

https://stormsha.com

3个月前 回复


avatar
杜赛 [博主] stormsha 么么哒! 2

刚去参观了贵站,很漂亮,功能也齐全,自愧不如yes

友链来一发?

3个月前 回复


avatar
pidada 么么哒! 1

博主,课程很详细,很适合初学者!yes

请教一个前端的问题:我按照你的教程来,为什么总是出来的前端界面的效果和你的不同呢?

比如:在这个章中,我的目录是显示在下面的

2个月前 回复


avatar
杜赛 [博主] pidada 么么哒! 1

说明你的模板写得和我不一样。仔细检查

2个月前 回复


avatar
pidada 杜赛 [博主] 么么哒! 1

博主,你这章中的前端代码的那些换行是特意的吗

2个月前 回复


avatar
杜赛 [博主] pidada 么么哒! 1

什么意思?

2个月前 回复


avatar
ac1864 么么哒! 2

过关,
markdown还是比较简单的。

1个月前 回复


avatar
sys0613 么么哒! 1

请问教程左侧这个目录列表,也是用markdown实现的么?还是用什么插件实现的?

12天前 回复


avatar
杜赛 [博主] sys0613 么么哒! 1

也是Markdown实现了,外加了一个智能侧边栏的脚本。教程后面章节有讲的。

11天前 回复