На высоком уровне я хотел создать базовый шаблон (baseex.j2), который использует вложенные циклы для циклического обхода вложенного dict списка dict списка dict списка.Я надеялся, что baseex.j2 абстрагирует циклы и другой специфический для jinja контент и оставит дочерний шаблон для описания содержимого этих вложенных блоков.
В1: Возможен ли такой подход?Q2: если нет, есть ли что-то подобное (мульти-наследование, рекурсивное для циклов с блоками) Q3: если возможно, что я делаю не так?
базовый шаблон 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))%
Так что, если я запускаю ex.json только через шаблон baseex.j2:
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
кдочерние блоки (что из документа не имеет значения (и не имеет значения)).