Como posso tornar uma estrutura de árvore (recursivo), utilizando um modelo de Django?

votos
47

Eu tenho uma estrutura de árvore na memória que eu gostaria para processar em HTML usando um modelo de Django.

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

Haverá algum objeto rootque é um Node, e childrené uma lista de Nodes. rootserá passado no conteúdo do modelo.

Eu encontrei esta uma discussão de como isso pode ser alcançado, mas o cartaz sugere que este pode não ser bom em um ambiente de produção.

Alguém sabe de uma maneira melhor?

Publicado 28/08/2008 em 12:43
fonte usuário
Em outras línguas...                            


10 respostas

votos
56

Usando withtag modelo, eu poderia fazer árvore de lista / recursiva.

Código de amostra:

template principal: assumindo 'all_root_elems' é uma lista de um ou mais raiz da árvore

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

tree_view_template.html torna o aninhado ul, lie utiliza nodevariável modelo como a seguir:

<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>
Respondeu 25/07/2012 em 08:21
fonte usuário

votos
25

Acho que a resposta canônica é: "Não".

O que você provavelmente deve fazer em vez disso é desvendar a coisa em sua vista de código, por isso é apenas uma questão de iteração sobre (in | de) mossas no modelo. Eu acho que eu faria isso anexando travessões e dedents a uma lista enquanto recursão através da árvore e, em seguida, enviar essa lista "diário de viagem" para o modelo. (o modelo, então, inserir <li>e </li>a partir dessa lista, criando a estrutura recursiva com "compreensão"-lo.)

Eu também tenho certeza que recursivamente incluindo arquivos de modelo é realmente uma errada maneira de fazê-lo ...

Respondeu 28/08/2008 em 13:47
fonte usuário

votos
18

isso pode ser muito mais do que você precisa, mas há um módulo django chamado 'mptt' - isto armazena uma estrutura de árvore hierárquica em um banco de dados SQL, e inclui modelos para exibição no código vista. você pode ser capaz de encontrar algo útil lá.

aqui está o link: django-mptt

Respondeu 28/08/2008 em 18:23
fonte usuário

votos
10

Sim, você pode fazê-lo. É um pequeno truque, passando o nome do arquivo para {% include%} como uma variável:

{% with template_name="file/to_include.html" %}
{% include template_name %}
{% endwith %}
Respondeu 24/09/2012 em 04:50
fonte usuário

votos
9

Django foi construído em um ajudante modelo para este cenário exato:

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

Respondeu 07/09/2008 em 09:49
fonte usuário

votos
7

Eu tive o mesmo problema e eu escrevi um tag. Eu sei que existem outras tags como este lá fora, mas eu precisava aprender a fazer marcas personalizadas de qualquer maneira :) Eu acho que ficou muito bem.

Leia a docstring para instruções de uso.

github.com/skid/django-recurse

Respondeu 05/06/2009 em 20:40
fonte usuário

votos
6

Estou muito tarde) Todos vocês usam tanto desnecessários com etiquetas, isto é como eu fazer recuesive:

no modelo principal:

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

em seguida, em 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 %}
Respondeu 26/10/2015 em 07:31
fonte usuário

votos
0

corrigir este:

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 exemplo - 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)
Respondeu 30/07/2017 em 09:50
fonte usuário

votos
0

Será que ninguém como dicts? Eu poderia estar faltando alguma coisa aqui, mas parece que a maneira mais natural de menus de configuração. Usando chaves como entradas e valores como links colocá-la em uma DIV / NAV e você vai longe!

De sua base

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

chamar este

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

Não tentei o padrão ou o ainda ordenou talvez você tem?

Respondeu 25/09/2014 em 19:06
fonte usuário

votos
-2

Eu tive um problema semelhante, porém eu tinha implementado pela primeira vez a solução usando JavaScript, e apenas posteriormente consideradas como eu teria feito a mesma coisa em modelos de Django.

Eu usei o utilitário de serializador para transformar uma lista off modelos em JSON, e usou os dados JSON como base para a minha hierarquia.

Respondeu 03/09/2008 em 13:25
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more