我正在尝试实现 this金贾nl2br
筛选。它工作正常,除了 <br>
它添加的正在被转义。这对我来说很奇怪,因为 <p>
的没有被转义,它们都在同一个字符串中。
我正在使用 flask ,所以 Jinja autoescape
已启用。当我找到 this guy 时,我真的很有希望说autoescape
和 escape(value)
可能导致双重转义,但删除了 escape()
没有帮助。
这是我修改后的代码及其输出:
@app.template_filter()
@evalcontextfilter
def nl2br(eval_ctx, value):
_paragraph_re = re.compile(r'(?:\r\n|\r(?!\n)|\n){2,}')
result = u'\n\n'.join(u'<p>%s</p>' % escape(p.replace(u'\r\n', u'<br>\n')) for p in _paragraph_re.split(value))
if eval_ctx.autoescape:
result = Markup(result)
return result
输入:
u'1\r\n2\r\n\r\n3\r\n4\r\n\r\n5\r\n6\r\n7'
输出:
<p>1<br>
2</p>
<p>3<br>
4</p>
<p>5<br>
6<br>
7</p>
期望的输出:
<p>1<br>2</p>
<p>3<br>4</p>
<p>5<br>6<br>7</p>
可能导致 <br>
的原因要转义但允许 <p>
的?
最佳答案
nl2br
过滤器不能正确处理标记对象。如果value
是 Markup,然后插入 <br>
标签将被转义。要修复它,<br>
标记也必须是标记:
@app.template_filter()
@evalcontextfilter
def nl2br(eval_ctx, value):
_paragraph_re = re.compile(r'(?:\r\n|\r(?!\n)|\n){2,}')
result = u'\n\n'.join(u'<p>%s</p>' % p.replace(u'\n', Markup('<br>\n'))
for p in _paragraph_re.split(value))
if eval_ctx.autoescape:
result = Markup(result)
return result
注意:我将行结尾标准化为 \n
.
这是对正在发生的事情的更详细解释:
拆分 Markup
对象,产生许多Markup
对象:
>>> Markup("hello there").split()
[Markup(u'hello'), Markup(u'there')]
根据 Jinja's documentation for Markup :
Operations on a markup string are markup aware which means that all arguments are passed through the escape() function.
回顾nl2br
的主要改造,我们可以看到发生了什么以及为什么它不起作用:
result = u'\n\n'.join(u'<p>%s</p>' % p.replace(u'\n', u'<br>\n')
for p in _paragraph_re.split(value))
u'\n\n'
和 u'<br>\n'
是 unicode 字符串,但是 p
是Markup
已从 value
拆分出来,这是一个标记对象。 p.replace
尝试将 unicode 字符串添加到标记对象 p
,但 Markup 对象首先正确拦截并转义字符串。
<p>
由于 Python 如何组装最终字符串,标签不会被转义,因为 %
格式化方法在 unicode 字符串上调用,它使用传递给它的元素的 unicode 表示。标记元素已经被声明为安全的,因此它们不会被进一步转义。 result
以 unicode 字符串结束。
关于python - 为什么这个 Jinja nl2br 过滤器会转义 <br >'s but not <p>' s?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12523725/