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としてレンダリングされます(つまり、表示されません)。私はフィルターによってbodyから抽出されたコードでdjangoエスケープ関数を使用して遊んでいますが、それを正しくすることはできません。コンテンツのエスケープについての私の理解は、十分に完了していないと思います。また、投稿の本文にエスケープバージョン(たとえば<!> lt;)を書き込もうとしましたが、テキストとして出力されます。
htmlを表示用にマークする最良の方法は何ですか?私はこれについてすべて間違っていますか?
ありがとう。
解決
ようやく理解する時間が見つかりました。美しいスープにコンテンツが取り込まれ、タグが含まれている場合、タグはリストのサブノードとしてリストされます。この行が原因です:
new_content = pygments.highlight(code.contents[0], lexer, formatter)
[0]はコードの他の部分を切り捨てますが、正しくデコードされていません。私の側のバグの発見が悪い。その行は次のものに置き換える必要があります:
new_content = pygments.highlight(code.decodeContents(), lexer, formatter)
ここでの教訓は、問題が何であるかを確認し、ライブラリがどのように機能するかを確認することです。