如何防止 Django 基本内联自动转义
Posted
技术标签:
【中文标题】如何防止 Django 基本内联自动转义【英文标题】:How to prevent Django basic inlines from autoescaping 【发布时间】:2012-04-13 22:02:53 【问题描述】:Django Basic Inlines 应用程序根据 app/model/id 组合从伪 html 语法呈现预先确定的模板。例如,如果您正在撰写博客文章,则可以插入保存在图像模型中的图像:
# In the admin
This is the body of my post.
<inline type="media.image" id="1" class="full">
模板然后采用render_inlines
过滤器,需要标记safe
才能正确呈现HTML:
# Template
post.body|render_inlines|safe
但即使使用safe
,过滤器仍会转义HTML,在源代码中创建&lt;p&gt;&lt;img src="..."&gt;&lt;p&gt;
。
根据文档,过滤器应使用mark_safe
以防止在过滤器级别自动转义,但parser.py
中的inlines
函数已使用mark_safe
。
在 Django 1.4 中是否需要进一步停止自定义过滤器层的自动转义?我似乎无法摆脱这种自动转义,无论是在
inlines
function 或
render_inlines
function.
我尝试使用autoescape=None
,但似乎也没有帮助。
【问题讨论】:
去掉 safe 和 % autoescape off % 的结果是什么? 没什么,同样的结果,这就是为什么我相信转义发生在过滤器级别而不是模板。如果某些内容已经被转义,则在模板中放置safe
或关闭autoescape
不会执行任何操作。已经很安全了。
【参考方案1】:
对此的另一个解决方案是将新代码转换为 BeautifulSoup 对象,并用该对象替换。这样漂亮的汤似乎表现得很好。
这会给你转义的 html:
soup = BeautifulSoup(html_doc)
body = soup.body
new_html = """<p> this is some deap code</p><a href="#">Pointless even</a>"""
body.replaceWith(new_html)
这使您的 html 未转义:
soup = BeautifulSoup(html_doc)
body = soup.body
new_html = """<p> this is some deap code</p><a href="#">Pointless even</a>"""
body.replaceWith(BeautifulSoup(new_html))
【讨论】:
【参考方案2】:我维护 Inline 应用程序的 a fork。 Richard 就这个问题联系了我,我可以追溯到 BeautifulSoup,而不是 Django。
问题在于 BeautifulSoup 的 replaceWith()
方法被用来用渲染的模板替换内联标记。 render_to_string()
的结果当然是一个字符串。当replaceWith()
接收到一个字符串时,它会将其转换为NavigableString
。由于 BeautifulSoup 期望 NavigbleString
s 是字符串,它假定它们是不安全的并转义任何 HTML 字符。结果是 Inline 的 inlines()
函数返回的值包含一堆 &gt;
和 &lt;
而不是 <
和 >
。
我在 Django 1.3 中没有注意到这个问题。当我查看时,BeautifulSoup 确实返回了转义的 HTML。 Django 的|safe
模板过滤器一定已经对之前转义的HTML 进行了转义。在 Django 1.4 中,它不再这样做了。 (它不应该那样做!)
我的解决方法是使用 BeautifulSoup 解析传入的值,并使用 BeautifulSoup 来查找所有内联标记,就像以前一样。而不是使用 BeautifulSoup 的 replaceWith()
方法将内联标记替换为呈现的内联模板,我现在只使用 Python 的普通旧 str.replace()
。我觉得有点蹩脚,将解析后的汤转换回字符串,然后进行字符串替换。但它有效。我部分想完全取消 BeautifulSoup 并使用正则表达式找到内联标记,但 we all know how that ends。如果有人有更好的主意,我会全力以赴!
修复最初是在 this commit 中实现的。我在下面的提交中改进了它,但显然 *** 只允许我发布最多两个链接,所以你必须自己找到那个!
【讨论】:
Django 的 |safe 从未进行过“转义”,它只是简单地将文本标记为不需要进一步转义。【参考方案3】:这是因为 render_to_string
here。转到inlines/app_model.html
和inlines/default.html
并在内容变量之后添加|safe
。
【讨论】:
您的意思是 app/templates/app/model_detail.html 和 app/templates/inlines/default.html,对吗?标记那些safe
?这就是我已经在做的事情。有人在帮助我,这可能是 BeautifulSoup 3.2.0 与 BeautifulSoup 3.2.1 的问题,以及您引用的行中 replaceWith
的更改方式。
不是model_detail.html
,而是该行使用的模板。您可以使用print
或 pdb 来检查它。在该行上,您的数据被渲染到模板中,然后在您调用内联的地方返回结果。您应该在外部和内部模板中禁用自动转义。以上是关于如何防止 Django 基本内联自动转义的主要内容,如果未能解决你的问题,请参考以下文章