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

StackOverflow https://stackoverflow.com/questions/32044

  •  09-06-2019
  •  | 
  •  

Pregunta

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

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

Habrá algún objeto root eso es un Node, y children es una lista de Nodes. root se pasará en el contenido de la plantilla.

he encontrado este Hubo una discusión sobre cómo se podría lograr esto, pero el cartel sugiere que esto podría no ser bueno en un entorno de producción.

¿Alguien sabe de una manera mejor?

¿Fue útil?

Solución

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

Lo que probablemente deberías hacer es desentrañar la cosa en tu vista código, por lo que es solo una cuestión de iterar sobre (in|de)dentaciones en la plantilla.Creo que lo haría agregando sangrías y sangrías a una lista mientras recorro el árbol y luego envío esa lista de "diarios de viaje" a la plantilla.(la plantilla luego insertaría <li> y </li> de esa lista, creando la estructura recursiva "comprendiéndola".)

También estoy bastante seguro de que incluir archivos de plantilla de forma recursiva es realmente una equivocado manera de hacerlo...

Otros consejos

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

Código de muestra:

plantilla principal:suponiendo que 'all_root_elems' es una 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 representa el anidado ul, li y usos node variable de plantilla como se muestra a continuación:

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

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

aquí está el enlace : django-mptt

Llego demasiado tarde) Todos ustedes usan tanto innecesarios con etiquetas, así es como lo hago de forma recursiva:

en plantilla principal:

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

luego en 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 %}

Si, puedes hacerlo.Es un pequeño truco, pasar el nombre de archivo a { % incluye %} como una variable:

{% with template_name="file/to_include.html" %}
{% include template_name %}
{% endwith %}

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

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

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

Lea la cadena de documentación para obtener instrucciones de uso.

github.com/skid/django-recurse

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

desde tu base

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

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

Aún no ha probado el predeterminado o el pedido, ¿quizás sí lo haya hecho?

corrige esto:

comentario_raíz.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 %}

comentario_árbol.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)

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.

Utilicé la utilidad serializador para convertir una lista de modelos en json y utilicé los datos json como base para mi jerarquía.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top