¿Cómo puedo renderizar una estructura de árbol (recursiva) usando una plantilla de django?


Tengo una estructura de árbol en memoria que me gustaría renderizar en HTML usando una plantilla de Django.

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

Habrá algún objeto root que a Node, y children es una lista de Nodes. root será aprobada en el contenido de la plantilla.

He encontrado esta una discusión de cómo esto podría lograrse, pero el cartel sugiere que esto podría no ser bueno en un entorno de producción.

¿Alguien sabe de una manera mejor?

Author: David Sykes, 2008-08-28

10 answers

Creo que la respuesta canónica es: "No".

Lo que probablemente deberías hacer en su lugar es desentrañar la cosa en tu código view, por lo que es solo una cuestión de iterar sobre (en|de)abolladuras en la plantilla. Creo que lo haría añadiendo sangrías y dedentes a una lista mientras recurres a través del árbol y luego enviando esa lista de "diario de viaje" a la plantilla. (la plantilla entonces insertaría <li> y </li> de esa lista, creando la estructura recursiva con " comprensión" se.)

También estoy bastante seguro de que incluir recursivamente archivos de plantilla es realmente una mal manera de hacerlo...

 27
Author: Anders Eurenius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-28 12:47:29

Usando la etiqueta de plantilla with, podría hacer lista de árbol/recursiva.

Código de ejemplo:

Plantilla principal: asumiendo que 'all_root_elems' es la lista de una o más raíces del árbol

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

Tree_view_template.html renderiza el anidado ul, li y utiliza node variable de plantilla de la siguiente manera:

<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>
 61
Author: Rohan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-13 22:19:20

Esto puede ser mucho más de lo que necesita, pero hay un módulo django llamado 'mptt' - este almacena una estructura jerárquica en una base de datos sql, e incluye plantillas para mostrar en el código de la vista. es posible que pueda encontrar algo útil allí.

Aquí está el enlace : django-mptt

 19
Author: dfarrell07,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-12 21:52:12

Sí, puedes hacerlo. Es un pequeño truco, pasando el nombre de archivo a {%include%} como una variable:

{% with template_name="file/to_include.html" %}
{% include template_name %}
{% endwith %}
 11
Author: Vladimir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-12 12:13:11

Django tiene un ayudante de plantilla integrado para este escenario exacto:

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

 9
Author: John,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-19 14:58:50

Llego demasiado tarde) Todos ustedes usan tanto innecesario con etiquetas, así es como lo hago recuesive:

En la plantilla principal:

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

Entonces en el menú.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 %}
 8
Author: Arthur Sult,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-26 07:31:07

Tuve el mismo problema y escribí una etiqueta de plantilla. Sé que hay otras etiquetas como esta por ahí, pero necesitaba aprender a hacer etiquetas personalizadas de todos modos :) Creo que resultó bastante bien.

Lea el docstring para obtener instrucciones de uso.

Github.com/skid/django-recurse

 7
Author: disc0dancer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-13 22:20:36

¿A nadie le gustan los dictados ? Puede que me esté perdiendo algo aquí, pero parecería la forma más natural de configurar los menús. El uso de claves como entradas y valores como enlaces pop en un DIV / NAV y listo!

Desde tu base

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

Llama a esto

# 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>

No ha probado el valor predeterminado o el ordenado, pero tal vez lo haya hecho ?

 0
Author: Carel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-25 18:06:37

Corrija esto:

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>

Por ejemplo - modelo:

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
Author: meg2mag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-31 07:32:03

Tuve un problema similar, sin embargo, primero implementé la solución usando JavaScript, y justo después consideré cómo habría hecho lo mismo en las plantillas de django.

Usé la utilidad serializer para convertir una lista de modelos en json, y usé los datos json como base para mi jerarquía.

 -2
Author: Staale,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-03 12:25:19