Django 实现 Markdown 语法和代码高亮


实现Markdown 语法显示

1. 安装Markdown

  • 进入虚拟环境使用 pip install markdown安装

2. detail 视图中渲染 Markdown

将markdown格式的文本渲染成html,只需要调用markdown库的markdown方法就可以了。
以下示例,需要渲染的内容存在Articlebody属性中。

blog/views.py

import markdown
from django.shortcuts import render, get_object_or_404
from .models import Article

def detail(request, pk):
    article = get_object_or_404(Article, pk=pk)
    # 记得在顶部引入 markdown 模块
    article.body = markdown.markdown(article.body,extensions=[
        'markdown.extensions.extra',
        'markdown.extensions.codehilite',
        'markdown.extensions.toc',
    ])
    return render(request, 'blog/detail.html', context={'article': article})

markdown.extensions函数说明

  • extra本身包含很多扩展
  • codehilite是语法高亮
  • toc是自动生成目录

3. safe标签

我们在发布的文章详情页没有看到预期的效果,而是类似于一堆乱码一样的 HTML 标签,这些标签本应该在浏览器显示它本身的格式,但是 Django 出于安全方面的考虑,任何的 HTML 代码在 Django 的模板中都会被转义(即显示原始的 HTML 代码,而不是经浏览器渲染后的格式)。为了解除转义,只需在模板标签使用 safe 过滤器即可,告诉 Django,这段文本是安全的,你什么也不用做。在模板中找到展示博客文章主体的 {{ article.text }} 部分,为其加上 safe 过滤器,{{ article.text|safe }},大功告成,这下看到预期效果了。

safe 是 Django 模板系统中的过滤器(Filter),可以简单地把它看成是一种函数,其作用是作用于模板变量,将模板变量的值变为经过滤器处理过后的值。例如这里 {{ article.text|safe }},本来 {{article.text }} 经模板系统渲染后应该显示 body 本身的值,但是在后面加上 safe 过滤器后,渲染的值不再是text 本身的值,而是由 safe 函数处理后返回的值。过滤器的用法是在模板变量后加一个 | 管道符号,再加上过滤器的名称。可以连续使用多个过滤器,例如 {{ var|filter1|filter2 }}
我们在发布的文章详情页没有看到预期的效果,而是类似于一堆乱码一样的 HTML 标签,这些标签本应该在浏览器显示它本身的格式,但是 Django 出于安全方面的考虑,任何的 HTML 代码在 Django 的模板中都会被转义(即显示原始的 HTML 代码,而不是经浏览器渲染后的格式)。为了解除转义,只需在模板标签使用 safe 过滤器即可,告诉 Django,这段文本是安全的,你什么也不用做。在模板中找到展示博客文章主体的 {{ article.text }} 部分,为其加上 safe 过滤器,{{ article.text|safe }},大功告成,这下看到预期效果了。

safe 是 Django 模板系统中的过滤器(Filter),可以简单地把它看成是一种函数,其作用是作用于模板变量,将模板变量的值变为经过滤器处理过后的值。例如这里 {{ article.text|safe }},本来 {{article.text }} 经模板系统渲染后应该显示 body 本身的值,但是在后面加上 safe 过滤器后,渲染的值不再是text 本身的值,而是由 safe 函数处理后返回的值。过滤器的用法是在模板变量后加一个 | 管道符号,再加上过滤器的名称。可以连续使用多个过滤器,例如 {{ var|filter1|filter2 }}

出现问题

  1. 出现'No module named 'mdx_markwdown'报错
    出现这个错误请检查你的单词拼写

代码高亮

1. 安装 Pygments

  • 进入虚拟环境使用 pip install markdown安装

搞定了,虽然我们除了安装了一下 Pygments 什么也没做,但 Markdown 使用 Pygments 在后台为我们做了很多事。如果你打开博客详情页,找到一段代码段,在浏览器查看这段代码段的 HTML 源代码,可以发现 Pygments 的工作原理是把代码切分成一个个单词,然后为这些单词添加 css 样式,不同的词应用不同的样式,这样就实现了代码颜色的区分,即高亮了语法。为此,还差最后一步,引入一个样式文件来给这些被添加了样式的单词定义颜色。

2. 引入样式文件

创建一个代码高亮的CSS样式(其中-S后面是风格样式,默认样式default是emacs,生成的文件名为styles.css):

(env) $: pygmentize -S default -f html -a .codehilite > styles.css

会在当前目录会产生一个styles.css 文件,将styles.css文件移到/static/css/ 目录,并在detail.html 文件head标签中添加样式

<link rel="stylesheet" href="{% static 'blogpost/css/styles.css' %}">

代码无法高亮

  1. 确保在渲染文本时添加了 markdown.extensions.codehilite 拓展,详情见上文。

  2. 确保安装了 Pygments。

  3. 确保代码块的 Markdown 语法正确,特别是指明该代码块的语言类型,具体请参见上文中 Markdown 的语法示例。

  4. 在浏览器端代码块的源代码,看代码是否被 pre 标签包裹,并且代码的每一个单词都被 span 标签包裹,且有一个 class 属性值。如果没有,极有可能是前几步中某个地方出了问题。

  5. 确保用于代码高亮的样式文件被正确地引入,具体请参见上文中引入样式文件的讲解。

  6. 有些样式文件可能对代码高亮没有作用,首先尝试用 github.css 样式文件做测试。

  7. 如果代码仍然不高亮,请在浏览器中检查class是否跟引入文件一致。
    Django 实现 Markdown 语法和代码高亮
    如果不一致将引入文件改成一样的就可以了
    Django 实现 Markdown 语法和代码高亮