Python Django-在呈现模板之前呈现模板标记
我有一个问题,我不太确定如何解决。我有一个模板,它将呈现一段文本,该文本本身将包含一个要动态更新的模板标记Python Django-在呈现模板之前呈现模板标记,python,django,templates,Python,Django,Templates,我有一个问题,我不太确定如何解决。我有一个模板,它将呈现一段文本,该文本本身将包含一个要动态更新的模板标记 <ul> {% for section in sections %} <li>{{ section.content | safe }}</li> {% endfor %} </ul> 然后,我需要动态更新节.content中的{{document.customer}标记。该标记在模板中可以很好地渲染,但不能作为也要渲染的各个
<ul>
{% for section in sections %}
<li>{{ section.content | safe }}</li>
{% endfor %}
</ul>
然后,我需要动态更新节.content中的{{document.customer}
标记。该标记在模板中可以很好地渲染,但不能作为也要渲染的各个部分的一部分。如何在模板中的节中呈现模板变量
我尝试用{%include“display\u lld\u sections.html”替换上面的内容,替换为sections=sections document=document%}
但这没有什么区别,因为我认为这只是将问题转移到另一个模板。我也看不出写一个自定义标记会有什么帮助,因为它仍然只对部分有效,而不是对部分中的内容有效,对吗
我还尝试了使用with
语句:
<ul>
{% for section in sections %}
{% with document=document %}
<li>{{ section.content | safe }}</li>
{% endwith %}
{% endfor %}
</ul>
虽然不是这样,但我怀疑解决这个问题的方法。这是否需要在我的视图或模型中使用代码来完成,而不是在我的模板中完成?您应该将部分。内容包装到模板中,并使用include
标记将其包含,如下所示:
lookup = re.compile(r'{{ *(\w+) *}}')
def interpolate(text, context):
replacer = lambda m: context.get(m.group(1), '')
return lookup.sub(replacer, text)
def in_your_view(self, whatever):
# some stuff
section_context = {
"customer": document.customer,
"foo": "bar",
}
for section in sections:
section.interpolated = interpolate(section.section, section_context)
{%include section.content_template%}
比方说,如果您的节是django模型实例,请将此属性添加到该模型中:
@property
def content_template(self):
from django.template.backends.django import Template
return Template(self.content)
当然,您可以为模板动态选择引擎,但在其他引擎中,包括模板对象可能无法工作。这取决于您需要的多功能性级别
- 如果内容实际上可以包含任何类型的模板功能,那么您将别无选择,只能将其作为模板。看看格温布利德的答案吧。但也有一些缺点:
- 主要缺点是Django不会缓存这些模板,因此每次都必须编译它们,这可能会对性能产生重大影响
- 此外,如果
内容可能来自不受信任的来源,请记住,将其作为模板将使其能够访问大量内部数据(上下文、上下文处理器公开的任何内容,如站点设置、所有类型的标记等)。如果我用内容制作一个部分:Hehe,我得到了你的{{{settings.DATABASES.default.PASSWORD}
- 但是,如果您只需要替换一小部分已知变量,您可以在视图中进行简单的字符串替换,查找
{{document.customer}
,并替换为值
如果你走这条路,也许你应该简化一点。我会这样做:
lookup = re.compile(r'{{ *(\w+) *}}')
def interpolate(text, context):
replacer = lambda m: context.get(m.group(1), '')
return lookup.sub(replacer, text)
def in_your_view(self, whatever):
# some stuff
section_context = {
"customer": document.customer,
"foo": "bar",
}
for section in sections:
section.interpolated = interpolate(section.section, section_context)
这将用customer替换{{customer}}
,用bar替换{{foo}}
,而不做任何模板工作。它是有意限制的,因此它不会提供对任何数据的访问,而是来自上下文的内容。而且它没有解析模板对性能的影响
现在您只需在视图中输出̀{{section.interpolated}}
,就完成了
什么是章节内容
?其他模板的结果?还是数据库中的一些文本?节是一个模型,而内容是该模型的一个字段。因此,当我调用一个部分查询集时,section.content是查询集中每个部分的内容字段。哇,谢谢。这需要考虑很多。老实说,我没有想到向用户开放模板语言会带来安全隐患。我想我将继续替换视图中特定的、已知的值。我的python知识仍然有限,因此我将花时间理解您的代码。此视图是否会将section.interpolated
添加到sections
中,因此在我的视图中,我仍然使用返回渲染(请求,'template.html',{'sections':sections}
,然后在我的模板中{%for sections%}{section.interpolated | safe} {%endfor%}
?谢谢。是的,你就是这样做的。至于安全方面的考虑,请小心使用|safe
,这会使Django假设变量中的任何内容都是安全的,这可能是一个问题,例如,
标记只会按原样被注入。再次感谢@spectras终于抽出时间来实现它,它的工作非常有魅力。
lookup = re.compile(r'{{ *(\w+) *}}')
def interpolate(text, context):
replacer = lambda m: context.get(m.group(1), '')
return lookup.sub(replacer, text)
def in_your_view(self, whatever):
# some stuff
section_context = {
"customer": document.customer,
"foo": "bar",
}
for section in sections:
section.interpolated = interpolate(section.section, section_context)