Django博客使用Markdown自动生成目录

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 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!