在较高的层次上,我想创建一个基本模板(baseex.j2),该模板使用嵌套循环在list dict列表的dict列表的嵌套dict上循环。我的希望是baseex.j2将抽象出循环和其他Jinja特定内容,并留下子模板来描述这些嵌套块的内容。
Q1:这种方法是否可能? 问题2:如果不是,是否有类似的东西(多继承,带有块的循环递归) 问题3:如果可能,我在做什么错了?
基本模板baseex.j2:
{%- for a in as %}
{%- set a_loop = loop %}
{%- block a scoped %}
{{a.name}} {{ a_loop.index }}
{%- for r in a.rs %}
{%- set r_loop = loop %}
{%- block r scoped %}
{{r.name}} {{ r_loop.index }}
{%- for f in r.fs %}
{%- set f_loop = loop %}
{%- block f scoped %}
{{f.name}} {{ f_loop.index }}
{%- endblock %}
{%- endfor %}
{%- endblock %}
{%- endfor %}
{%- endblock %}
{%- endfor %}
数据示例ex.json:
{"as":[{"name":"a_a","rs":[{"name":"b_r","fs":[{"name":"c_f"},{"name":"d_f"}]}]},{"name":"e_a","rs":[{"name":"f_r","fs":[{"name":"g_f"},{"name":"h_f"}]}]}]}
CLI接受json输入和多个jinja模板j2dirjson:
#!/usr/bin/env python
# Inputs: Jinja2 Template Dir, Target Template and JSON file
# Output: rendered result to stdout
from jinja2 import Environment, FileSystemLoader, Template
import json5 as json
import sys
j2_env = Environment(loader=FileSystemLoader(sys.argv[1]))
template = j2_env.get_template(sys.argv[2])
with open(sys.argv[3]) as fd:
data = json.load(fd)
print(template.render(data))%
因此,如果我仅通过baseex.j2模板运行ex.json:
j2dirjson . baseex.j2 ex.json
我得到了预期的输出:
a_a 1
b_r 1
c_f 1
d_f 2
e_a 2
f_r 1
g_f 1
h_f 2
现在,我创建一个子模板be.md.j2:
{%- extends "baseex.j2" %}
{%- block a %}
{{a_loop.index}}
{%- block r %}
{{r_loop.index}}
{%- block f %}
{%- endblock %}
{%- endblock %}
{%- endblock %}
并运行它:
j2dirjson . be.md.j2 ex.json
但是得到这个结果:
Traceback (most recent call last):
File "j2dirjson", line 20, in <module>
print(template.render(data))
File "/usr/lib/python2.7/dist-packages/jinja2/environment.py", line 1008, in render
return self.environment.handle_exception(exc_info, True)
File "/usr/lib/python2.7/dist-packages/jinja2/environment.py", line 780, in handle_exception
reraise(exc_type, exc_value, tb)
File "./be.md.j2", line 1, in top-level template code
{%- extends "baseex.j2" %}
File "./baseex.j2", line 3, in top-level template code
{%- block a scoped %}
File "./be.md.j2", line 4, in block "a"
{%- block r %}
File "./be.md.j2", line 5, in block "r"
{{r_loop.index}}
File "/usr/lib/python2.7/dist-packages/jinja2/environment.py", line 430, in getattr
return getattr(obj, attribute)
jinja2.exceptions.UndefinedError: 'r_loop' is undefined
我看过文档: http://jinja.pocoo.org/docs/2.10/templates/#block-nesting-and-scope
并尝试了类似的操作,例如将scoped
添加到子块(与文档无关(无关紧要))。