问题描述
我试图实现 Jinja nl2br
code>过滤器。除了它所添加的< br> 被转义以外,它正常工作。这对我来说很奇怪,因为< p> 没有被转义,而且它们都在同一个字符串中。我正在使用烧瓶,所以启用了Jinja autoescape 。当我找到时,我真的很有希望说 autoescape 和 escape(value)可能会导致双重转义,但删除转义)没有帮助。
这是我修改过的代码,它的输出:
@evalcontextfilter
def nl2br(eval_ctx,value):
_paragraph_re = re.compile(r'(?:\\ \\ r \ n | \r(?!\\\
)| \\\
){2,}')
result = u'\\\
\\\
'.join(u'< p> (value))$ b $;%s(< / p> b如果eval_ctx.autoescape:
result =标记(结果)
返回结果
input:
u'1 \r\\\
2\r\\\
\r\\\
3\ r\\\
4\r\\\
\ r\\\
5\r\\\
6\r\\\
7'
输出: p>
< p> 1& lt; br& gt;
2< / p>
< p> 3& lt; br& gt;
4< / p>
< p> 5& lt;& gt;
6& lt; br& gt;
7< / p>
所需输出:
< p为H. 1·峰; br> 2'; / p为H.
< p> 3< br> 4< / p>
< p> 5< br> 6< br> 7< / p>
什么可能导致< br> 要被转义,但是允许< p> 的?
nl2br 过滤器不能正确处理标记对象。如果 value 是标记,则插入的< br> 标签将被转义。要解决这个问题,< br> 标记也必须是标记:
@ app.template_filter()
@evalcontextfilter
def nl2br(eval_ctx,value):
_paragraph_re = re.compile(r'(?:\r\\\
| \ r(?!\ n)| \\\
){2,}')
result = u'\\\
\\\
'.join(u'< p>%s< / p> (p'replace(''''n',Markup('< br> \\\
'))
for _paragraph_re.split(value))
if eval_ctx.autoescape:
结果=标记(结果)
返回结果
注意: \\\
。
以下是对发生的更详细的解释:
拆分标记对象,产生许多标记对象:
>>> Markup(hello there)。split()
[Markup(u'hello'),Markup(u'there')]
根据 Jinja的Markup文档 $ b
回顾 nl2br 的主要转换,我们可以看到发生了什么, 't work:
result = u'\\\
\\\
'.join(u'%s ',u'br> \\\
')
for _paragraph_re.split(value))
$ b $ p $ c $ u code code code $> u'< br> \ n'是unicode字符串,但 p 是标记已从值中拆分,whi ch是一个标记对象。 p.replace 尝试向标记对象 p 添加一个unicode字符串,但标记对象正确地截取并转义字符串首先。
$ b< p> 标签不会因为Python组装最终字符串而被转义,在unicode字符串上调用%格式化方法,它使用传递给它的元素的Unicode代表。标记元素已经被宣布为安全的,所以他们不会再逃脱。 result 以unicode字符串结尾。
I am attempting to implement this Jinja nl2br filter. It is working correctly except that the <br>'s it adds are being escaped. This is weird to me because the <p>'s are not being escaped and they are all in the same string.
I am using flask so the Jinja autoescape is enabled. I was really hopeful when I found this guy saying the autoescape and the escape(value) may have been causing double escaping, but removing the escape() did not help.
Here is my modified code and it's output:
@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 resultinput:
u'1\r\n2\r\n\r\n3\r\n4\r\n\r\n5\r\n6\r\n7'output:
<p>1<br> 2</p> <p>3<br> 4</p> <p>5<br> 6<br> 7</p>desired output:
<p>1<br>2</p> <p>3<br>4</p> <p>5<br>6<br>7</p>What could be causing the <br>'s to be escaped but allowing the <p>'s?
解决方案The nl2br filter doesn't handle Markup objects correctly. If value is Markup, then the inserted <br> tags will be escaped. To fix it, the <br> tag must be Markup too:
@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 resultNote: I normalized line endings to \n.
Here's a longer explanation of what's happening:
Splitting Markup objects, produces many Markup objects:
>>> Markup("hello there").split() [Markup(u'hello'), Markup(u'there')]According to Jinja's documentation for Markup:
Looking back at the main transformation of nl2br, we can see what's happening and why it didn't work:
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' and u'<br>\n' are unicode strings, but p is Markup having been split from value, which is a Markup object. p.replace tries to add a unicode string to Markup object p, but the Markup object correctly intercepts and escapes the string first.
The <p> tags aren't escaped because of how Python assembles the final string, since the % formatting method is called on a unicode string, it uses the unicode representation of the elements passed to it. The Markup elements have already been declared safe, so they aren't escaped any further. result ends up as a unicode string.
这篇关于为什么这个Jinja nl2br过滤器逃避了,而不是< p>的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!