如何防止Django基本内联自动转换

时间:2012-03-30 08:13:40

标签: python django django-templates django-template-filters

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来阻止过滤器级别的自动转移,但inlines中的parser.py功能已使用mark_safe

Django 1.4中是否还需要一些东西来停止自定义过滤层的自动转换?我似乎无法在

中摆脱这种自动转移

我尝试使用autoescape=None,这似乎也无济于事。

3 个答案:

答案 0 :(得分:1)

我维护了内联应用的a fork。 Richard和我联系了这个问题,我能够追溯到BeautifulSoup,而不是Django。

问题在于,使用BeautifulSoup的replaceWith()方法将内联标记替换为渲染模板。 render_to_string()的结果当然是一个字符串。当replaceWith()收到字符串时,会将其转换为NavigableString。由于BeautifulSoup期望NavigbleString是字符串,因此它假定它们不安全并且转义任何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中实现的。我在下面的提交中改进了它,但显然StackOverflow只允许我发布最多两个链接,所以你必须自己找到它!

答案 1 :(得分: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 :(得分:0)

这是因为render_to_string here。转到inlines/app_model.htmlinlines/default.html,然后在内容变量之后添加|safe