Как я могу отобразить древовидную структуру (рекурсивную), используя шаблон django? - PullRequest
54 голосов
/ 28 августа 2008

У меня есть древовидная структура в памяти, которую я хотел бы отобразить в HTML, используя шаблон Django.

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

Будет некоторый объект root, представляющий собой Node, а children - это список Node с. root будет передано в содержании шаблона.

Я обнаружил это одно обсуждение того, как этого можно достичь, но постер предполагает, что это может быть не очень хорошо в производственной среде.

Кто-нибудь знает лучший способ?

Ответы [ 10 ]

67 голосов
/ 25 июля 2012

Используя with шаблон тега, я мог бы создать древовидный / рекурсивный список.

Пример кода:

основной шаблон: при условии, что 'all_root_elems' является списком одного или нескольких корней дерева

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

tree_view_template.html отображает вложенные ul, li и использует переменную шаблона node, как показано ниже:

<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>
27 голосов
/ 28 августа 2008

Я думаю, что канонический ответ: «Не надо».

Что вам, вероятно, следует сделать вместо этого, это распутать вещь в вашем представлении кода, так что это просто вопрос перебора (in | de) вмятин в шаблоне. Я думаю, что я сделал бы это, добавляя отступы и отступы в список, повторяя через дерево, и затем отправляя этот список "путешествий" в шаблон. (шаблон затем вставит <li> и </li> из этого списка, создав рекурсивную структуру с «пониманием» этого.)

Я также уверен, что рекурсивное включение файлов шаблонов действительно неправильный способ сделать это ...

20 голосов
/ 28 августа 2008

это может быть намного больше, чем нужно, но есть модуль django под названием 'mptt' - он хранит иерархическую древовидную структуру в базе данных sql и включает шаблоны для отображения в коде представления. Вы можете найти там что-нибудь полезное.

вот ссылка: django-mptt

12 голосов
/ 26 октября 2015

я опоздал) Все вы используете столько ненужных с тегами, вот как я получаю:

в основном шаблоне:

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

затем в 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 %}
11 голосов
/ 24 сентября 2012

Да, вы можете сделать это. Это маленькая хитрость, передача имени файла {% include%} в качестве переменной:

{% with template_name="file/to_include.html" %}
{% include template_name %}
{% endwith %}
9 голосов
/ 07 сентября 2008

Django имеет встроенный помощник по шаблону для этого точного сценария:

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

8 голосов
/ 05 июня 2009

У меня была такая же проблема, и я написал тег шаблона. Я знаю, что есть и другие подобные теги, но мне все равно нужно было научиться создавать собственные теги :) Я думаю, что это оказалось довольно хорошо.

Прочтите документацию для инструкций по использованию.

github.com / занос / Джанго-рекурсию

0 голосов
/ 30 июля 2017

исправить это:

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>

например - модель:

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 голосов
/ 25 сентября 2014

Никто не любит диктов? Возможно, я что-то здесь упускаю, но это может показаться наиболее естественным способом настройки меню. Используя ключи в качестве записей и значения в качестве ссылок, вставьте их в DIV / NAV, и все!

С вашей базы

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

позвоните

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

Он еще не пробовал по умолчанию или заказал, может быть, у вас есть?

0 голосов
/ 03 сентября 2008

У меня была похожая проблема, однако я сначала реализовал решение с использованием JavaScript, а потом подумал, как бы я сделал то же самое в шаблонах django.

Я использовал утилиту сериализатора, чтобы превратить список моделей в json, и использовал данные json в качестве основы для моей иерархии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...