Django语法高亮导致字符转义问题

1 投票
1 回答
615 浏览
提问于 2025-04-15 15:17

我一直在做自己的基于Django的博客(就像大家一样,我知道),想通过这个项目来提升我的Python技能。我觉得加一些代码高亮效果会很不错。于是我查看了一些现成的代码片段,决定把几个结合起来,自己写一个代码高亮的模板过滤器,使用了Beautiful Soup和Pygments。效果如下:

from django import template
from BeautifulSoup import BeautifulSoup
import pygments
import pygments.lexers as lexers
import pygments.formatters as formatters

register = template.Library()

@register.filter(name='pygmentize')
def pygmentize(value):
    try:
        formatter = formatters.HtmlFormatter(style='trac')
        tree = BeautifulSoup(value)
        for code in tree.findAll('code'):
            if not code['class']: code['class'] = 'text'
            lexer = lexers.get_lexer_by_name(code['class'])
            new_content = pygments.highlight(code.contents[0], lexer, formatter)
            new_content += u"<style>%s</style>" % formatter.get_style_defs('.highlight')
            code.replaceWith ( "%s\n" % new_content )
        content = str(tree)
        return content
    except KeyError:
        return value

这个过滤器会寻找像这样的代码块,并为其添加高亮和相关样式:

<code class="python">
    print "Hello World"
</code>

一切都运行得很好,直到我包含的一个代码块里有一些HTML代码。现在,我知道我需要的所有HTML,所以我直接在博客文章中写这些内容,并在渲染模板时,把文章的主体标记为安全:

{{ post.body|pygmentize|safe }}

这样做的结果是,代码块中的任何HTML都会被当作HTML渲染(也就是说,不会显示出来)。我尝试过在我的过滤器提取的代码上使用Django的转义函数,但总是觉得不太对劲。我觉得我对内容转义的理解还不够全面。我也试过在文章主体中写转义后的版本(比如用<),但它最终只是显示为文本。

那么,标记HTML以便显示的最佳方法是什么呢?我是不是走错了方向?

谢谢。

1 个回答

1

我终于找到时间来搞清楚这个问题。当Beautiful Soup抓取内容时,如果里面有标签,这个标签会作为列表的一个子节点出现。问题出在这一行:

new_content = pygments.highlight(code.contents[0], lexer, formatter)

这里的[0]把代码的另一部分给截断了,并不是说它解码错了。真是我没发现问题。那一行需要换成:

new_content = pygments.highlight(code.decodeContents(), lexer, formatter)

从中我们可以学到,要确保你知道问题是什么,并且要了解你使用的库是怎么工作的。

撰写回答