Рекурсия Jinja2 по словарю и наборам python

Я перебираю словарь в шаблоне jinja, который имеет почти бесконечное количество дочерних элементов. дети содержат наборы и словари. Я пытаюсь перебрать следующий набор данных и распечатать его через 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?


person Daniel Plas Rivera    schedule 09.03.2017    source источник


Ответы (1)


После изучения в течение некоторого времени, я понял это.

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   
person Daniel Plas Rivera    schedule 10.03.2017