Jinja2 递归 python 字典和集合

Jinja2 recursion over python dictionary and sets

我在一个神社模板中循环字典,它几乎有无穷无尽的 children。 children 包含集合和字典。我正在尝试遍历以下数据集并通过 jinja 打印它,如下例所示:

EYE
COURSES
CLASS_0E
CLASS_0F
EYE|MIT
COURSES
CLASS_1E
CLASS_2F
EYE|MIT|NIT
COURSES
CLASS_1X
CLASS_1D
EYE|MIT|NIT|XXX
COURSES
CLASS_4X
EYE|EDX
COURSES
CLASS_9A
CLASS_9B

这是使用的数据集:

SCHOOL = {
  'EYE': {
    'COURSES': {
      'CLASS_0E',
      'CLASS_0F'
    },
    'EYE|MIT': {
      'COURSES': {
        'CLASS_1E',
        'CLASS_2F'
      },
      'EYE|MIT|NIT': {
        'COURSES': {
          'CLASS_1X',
          'CLASS_1D'
        },
        'EYE|MIT|NIT|XXX': {
          'COURSES': {
            'CLASS_4X'
          }
        }
      },
      'EYE|EDX': {
        'COURSES': {
          'CLASS_9A',
          'CLASS_9B'
        }
      }
    }
  }
}

这是我到目前为止所做的尝试循环但没有成功。

from jinja2 import Template

template = Template(
"""
  {% for key, value in tree.items() recursive %}
    {{key}}
  {% if key == "COURSES" %}
    COURSES
    {{loop(value.items())}}
  {% else  %}
     * GOTO INTO THE NEXT CHILD AND REPEAT THE PROCESS *
  {% endif %}
  {% endfor%}
""")

print(template.render(tree = SCHOOL))

我如何解决 Jinja2 中的这个递归问题?

研究了一段时间后,我想通了。

from jinja2 import Template

template = Template("""
{%- macro recurse(n) %}
    {%- for key, value in n.items() %}
        {%- if key is not equalto 'COURSES' %}
            {{key}}
        {%- endif %}
        {%- if 'COURSES' in value and value is iterable %}
            COURSES
            {%- for item in value['COURSES'] %}
                {{item}}
            {%- endfor %}
        {%- endif %}
        {%- if value.items is defined %}
            {{recurse(value)}}
        {%- endif %}
    {%- endfor %}
{%- endmacro %}
{{ recurse(tree) }}
""")

print(template.render(tree=SCHOOL))

Jinja 模板引擎有很多 python 中没有的条件。但是 Jinja 关心空格,所以你需要像这样格式化上面的代码:

from jinja2 import Template

template = Template("""
{% macro recurse(n) %}{% for key, value in n.items() %}{% if key is not equalto 'COURSES' %}{{key}}{% endif %}{% if 'COURSES' in value and value is iterable %}
COURSES{% for item in value['COURSES'] %}
{{item}}{% endfor %}{% endif %}{% if value.items is defined %}   
{{recurse(value)}}{% endif%}{% endfor %}{% endmacro %}{{ recurse(tree) }}
""")

print(template.render(tree=SCHOOL))

这将给我所需的以下输出:

EYE
COURSES
CLASS_0E
CLASS_0F   
EYE|MIT
COURSES
CLASS_1E
CLASS_2F   
EYE|MIT|NIT
COURSES
CLASS_1X
CLASS_1D   
EYE|MIT|NIT|XXX
COURSES
CLASS_4X   
EYE|EDX
COURSES
CLASS_9B
CLASS_9A