Django template nested loop

Hi!

I have this model:

class Category(models.Model):
    name = models.CharField(max_length=255)
    parent = models.ForeignKey('self', on_delete=models.DO_NOTHING, blank=True, null=True, related_name='children')

    def __str__(self):
        return self.name

What i want to do is build a tree with categories that have children, for example

Category1
Category1-1
Category1-1-1
Category2
Category2-2

But i want to nested categories until categories that have no children and after that show products related to that category

Is this possible?

Yes it is possible.

However, there’s a lot more to this topic. If you’re working with any kind of tree structure implemented in a relational database, you will want to consider a more robust implementation of your models.

At a minimum, you’ll want to look at django-treebeard, django-mptt, and django-treenode.

Also see the texts and links at:

Thanks!

I was reading about django-treebeard

Can you explain me how i can do what i want using it?

I’d need you to be a lot more specific of what exactly it is you’re trying to accomplish.

I’ve products and each product has a category.

Now, the categories could’ve a parent, so i want to build a tree with the main categories (categories with no parents) and their children (every children could’ve children too)

So the models with django-treebeard is:

class Category(MP_Node):
    name = models.CharField(max_length=255)
    parent = models.ForeignKey('self', on_delete=models.DO_NOTHING, blank=True, null=True, related_name='children')

So how i can build a tree in my django template with the categories?

I need you to provide more details. What precisely do you mean by “build a tree”? Do you have an idea of the html you’re trying to generate?

I wanna make something with

    and
  • , like:

    <!-- Main categories -->
    <u>
        <li>
            Father 1
            <!-- Father 1's children -->
            <ul>
                 <li>
                    First father 1 child
                    <ul>
                        <!-- This has to continue until find a child without children -->
                   </ul>
                </li>
            </ul>
        </li>
    </ul>
    

    The idea is get an structure like below

    Screen Shot 2022-01-07 at 10.10.09

Cool. So it’s a depth-first rendering of a tree.

First, since you’re using an MP_Node, you no longer need a separate parent field.

Given an instance of Category named category, category.get_parent() retrieves the parent of that node, and category.get_children() retrieves the child nodes.

Rendering this as a tree structure can be done using a recursive use of a template.

For example, you could have a render_nodes.html template that looks something like this:

<li>{{ category.name }}
<ul>
{% for children in category.get_children %}
{% include "render_nodes.html" with category=children only %}
{% endfor %}
</ul>
</li>

which is then started in your parent template with something like:

<ul>
{% include "render_nodes.html" with category=root_node only %}
</ul>

(Obviously this is illustrative and not definitive.)

Now, as a side note - if this is going to be something rendered frequently, like a menu, you are not going to want to generate this with every request. As written, this is going to generate N+1 queries. You will want to do some sort of caching on that result.