How can I render a tree structure (recursive) using a django template?

I have a tree structure in memory that I would like to display in HTML using a Django template.

class Node(): name = "node name" children = [] 

There will be some root object, which is Node , and children , a list of Node s. root will be passed in the contents of the template.

I found this one discussion of how this can be achieved, but the poster suggests that this may not be good in a production environment.

Does anyone know a better way?

+47
python django
Aug 28 '08 at 11:43
source share
10 answers

I think the canonical answer is "Don't."

What you should probably do is unravel the thing in your code of view, so this is just a matter of iterating (in | de) the dents in the template. I think I would do this by adding indentation and separators to the list, recursing through the tree, and then sending this โ€œtravelogueโ€ list to the template. (the template then inserts <li> and </li> from this list, creating a recursive structure with an "understanding" of it.)

I am also sure that recursively, including template files, this is really the wrong way to do this ...

+26
Aug 28 '08 at 12:47
source share
โ€” -

Using the template tag with , I could make a tree / recursive list.

Code example:

Basic pattern: it is assumed that "all_root_elems" is a list of one or more tree roots

 <ul> {%for node in all_root_elems %} {%include "tree_view_template.html" %} {%endfor%} </ul> 

tree_view_template.html displays the nested ul , li and uses the node template variable, as shown below:

 <li> {{node.name}} {%if node.has_childs %} <ul> {%for ch in node.all_childs %} {%with node=ch template_name="tree_view_template.html" %} {%include template_name%} {%endwith%} {%endfor%} </ul> {%endif%} </li> 
+53
Jul 25 '12 at 7:21
source share

it may be more than you need, but there is a django module called "mptt" - it stores a hierarchical tree structure in the sql database and includes templates for display in the view code. you might find something useful there.

link here: django-mptt

+18
Aug 28 '08 at 17:23
source share

Yes you can do it. This is a little trick by passing the file name {% include%} as a variable:

 {% with template_name="file/to_include.html" %} {% include template_name %} {% endwith %} 
+10
Sep 24 '12 at 3:50
source share

Django has a built-in template helper for this exact scenario:

https://docs.djangoproject.com/en/dev/ref/templates/builtins/#unordered-list

+9
07 Sep '08 at 8:49
source share

I had the same problem and I wrote a template tag. I know that there are other tags like this, but I needed to learn how to create custom tags :) I think everything worked out very well.

Read the docstring statement to use.

github.com/skid/django-recurse

+7
Jun 05 '09 at 19:40
source share

I'm too late) You all use so many unnecessary tags with , this is how I repeat:

in the main template:

 <!-- lets say that menu_list is already defined --> <ul> {% include "menu.html" %} </ul> 

then in menu.html:

 {% for menu in menu_list %} <li> {{ menu.name }} {% if menu.submenus|length %} <ul> {% include "menu.html" with menu_list=menu.submenus %} </ul> {% endif %} </li> {% endfor %} 
+4
Oct 26 '15 at 7:31
source share

Doesn't anyone like to dictate? Maybe I missed something, but this is perhaps the most natural way to customize the menu. Using keys as records and values โ€‹โ€‹when links appear in DIV / NAV and go away!

From your base

 # Base.html <nav> {% with dict=contents template="treedict.html" %} {% include template %} {% endwith %} <nav> 

call it

 # TreeDict.html <ul> {% for key,val in dict.items %} {% if val.items %} <li>{{ key }}</li> {%with dict=val template="treedict.html" %} {%include template%} {%endwith%} {% else %} <li><a href="{{ val }}">{{ key }}</a></li> {% endif %} {% endfor %} </ul> 

He did not try by default or ordered, perhaps you have one?

0
Sep 25 '14 at 18:06
source share

fix it:

root_comment.html

 {% extends 'students/base.html' %} {% load i18n %} {% load static from staticfiles %} {% block content %} <ul> {% for comment in comments %} {% if not comment.parent %} ## add this ligic {% include "comment/tree_comment.html" %} {% endif %} {% endfor %} </ul> {% endblock %} 

tree_comment.html

 <li>{{ comment.text }} {%if comment.children %} <ul> {% for ch in comment.children.get_queryset %} # related_name in model {% with comment=ch template_name="comment/tree_comment.html" %} {% include template_name %} {% endwith %} {% endfor %} </ul> {% endif %} </li> 

for example - model:

 from django.db import models from django.contrib.auth.models import User from django.utils.translation import ugettext_lazy as _ # Create your models here. class Comment(models.Model): class Meta(object): verbose_name = _('Comment') verbose_name_plural = _('Comments') parent = models.ForeignKey( 'self', on_delete=models.CASCADE, parent_link=True, related_name='children', null=True, blank=True) text = models.TextField( max_length=2000, help_text=_('Please, your Comment'), verbose_name=_('Comment'), blank=True) public_date = models.DateTimeField( auto_now_add=True) correct_date = models.DateTimeField( auto_now=True) author = models.ForeignKey(User) 
0
Jul 30 '17 at 9:50
source share

I had a similar problem, however, I first implemented the solution using JavaScript, and immediately thought how I would do the same in django templates.

I used the serializer utility to turn the list from models to json, and used json data as the basis for my hierarchy.

-2
Sep 03 '08 at 12:25
source share



All Articles