Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jinja2 recursive loop vs dictionary

Tags:

python

jinja2

I have the following dictionary:

{'a': {'b': {'c': {}}}}

And the following Jinja2 template:

            {% for key in dictionary recursive %}

            <li>{{ key }}
            {% if dictionary[key] %}
                <ul>{{ loop(dictionary[key]) }}</ul>
            {% endif %}
            </li>

        {% endfor %}

But Jinja2 always output:

<ul>
    <li>a</li>
    <ul>
        <li>b</li>
    </ul>
</ul>

My understood is that using recursive, it would show me the "c" element too, but it only works for a depth of 2. Why is dictionary not changing to the dictionary[key] at every loop iteration ? The dictionary is always the original dictionary.

like image 398
Tarantula Avatar asked Dec 09 '11 23:12

Tarantula


1 Answers

You're right, dictionary isn't being updated in the recursion calls, and the loop cannot continue because the keys aren't found.

A workaround to this problem is using just the variables assigned in the for loop. In the dictionary example, this means to iterate through the items of the dictionary instead of just the keys:

from jinja2 import Template

template = Template("""                                                     
{%- for key, value in dictionary.items() recursive %}                       
  <li>{{ key }}                                                             
    {%- if value %}                                                         
      Recursive {{ key }}, {{value}}                                        
      <ul>{{ loop(value.items())}}</ul>                                     
    {%- endif %}                                                            
  </li>                                                                     
{%- endfor %}                                                               
""")

print template.render(dictionary={'a': {'b': {'c': {}}}})

The output of this script is:

<li>a
    Recursive a, {'b': {'c': {}}}
    <ul>
<li>b
    Recursive b, {'c': {}}
    <ul>
<li>c
</li></ul>
</li></ul>
</li>

where you can see that recursion on the b key works fine because both key and value are updated on each iteration of the loop (I added the "Recursive key, value" message to the template to make it clear).

like image 62
jcollado Avatar answered Sep 20 '22 18:09

jcollado