Home > Mobile >  Recursively navigating through dictionary in the django template
Recursively navigating through dictionary in the django template

Time:05-24

I have a dictionary of unknown depth which I want to display in my Django template. This dictionary represents the structure of the subfolders inside of a folder. My goal is to display it with the parent subfolders before their children, which would be indented to show that they're children of that folder.

So to explain with an example, if I have the following dictionary:

{'Script Hello': 
    {'Script Hello World': 
        {'Script Hello World 2': None, 
         'Script Hello World 3': None}}, 
 'Script Hello World 4': None, 
 'Script Hello World 5': 
    {'Script Hello World 6': None}}

I want it to be displayed like this :

. Script Hello
    . Script Hello World
        . Script Hello World 2
        . Script Hello World 3

. Script Hello World 4

. Script Hello World 5
    . Script Hello World 6

I've done a small code that does the job if the depth if at most 3 (to determine what I really wanted), but couldn't find a way to make it recursive.

My code is this :

{% for key, values in list.items %}
    <li> {{ key }}
        <ul>
            {% for key,values in values.items %}
                <li>{{ key }}</li>
                    <ul>
                        {% for key,values in values.items %}
                            <li>{{ key }}</li>
                        {% endfor %}
                    </ul>
            {% endfor %}
        </ul>
    </li>
{% endfor %}

I tried using Javascript to make a quick function to navigate through my dictionary and display its content, however I couldn't find how to get my dictionary as is in my Js function, I was always getting it escaped and wasn't able to use it, even after trying solutions like this one.

So I'd like your help in order to display my dictionary in my template recursively, which I didn't manage to do, even after trying all I could think of.

CodePudding user response:

I think the simplest solution is to use a custom template tag:

from django.utils.safestring import mark_safe

def get_data(data):
    text = "<ul>"
    for k, v in data.items():
       text  = f'<li>{k}<li>'
       if isinstance(v, dict):
           text  = get_data(v)  # recursively calling to get the lists
       else:  # this else block can be removed if you don't need it
           text  = f'<li>{v}</li>'
    text  = "</ul>"
    return text
       

@register.filter(is_safe=True)
def render_dict(data):
    text = get_data(data)
    return mark_safe(text)

More information can be found in the documentation.

  • Related