Django语法高亮导致字符转义问题
我一直在做自己的基于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)
从中我们可以学到,要确保你知道问题是什么,并且要了解你使用的库是怎么工作的。