这是另一种在渲染后保留未定义的双花括号表达式的方法,包括那些包含“多级”(点标记)引用以及任何其他引用的方法。
Willy Pregliasco 提供的答案不支持保留未定义的列表类型,例如{{ some_list[4] }},这是我需要的。下面的解决方案解决了这个问题,以及所有可能的架构类型。
这个想法是解析输入模板并尝试使用提供的上下文解析每个表达式。任何无法解析的,我们都替换为一个简单地解析为字符串的原始表达式的双花括号表达式。
在调用渲染之前通过下面的preserve_undefineds_in_template 函数传递你的模板和上下文:
from jinja2 import Template, StrictUndefined, UndefinedError
import re
def preserve_undefineds_in_template(template, context):
patt = re.compile(r'(\{\{[^\{]*\}\})')
j2_expressions = patt.findall(template)
for j2_expression in set(j2_expressions):
try:
Template(j2_expression, undefined=StrictUndefined).render(context)
except UndefinedError:
template = template.replace(j2_expression, f"{{% raw %}}{j2_expression}{{% endraw %}}")
return template
例子:
template = """hello {{ name }}, {{ preserve_me }} {{ preserve.me[2] }}"""
context = { "name": "Alice" }
# pass it through the preserver function
template = preserve_undefineds_in_template(template, context)
# template is now:
# hello {{ name }}, {% raw %}{{ preserve.me }}{% endraw %} {% raw %}{{ preserve.me.too[0] }}{% endraw %}
# render the new template as normal
result = Template(template).render(context)
print(result)
输出是:
hello Alice, {{ preserve_me }} {{ preserve.me[2] }}