Как я могу визуализировать древовидную структуру (рекурсивную) с использованием шаблона django?
У меня есть древовидная структура в памяти, которую я бы хотел отобразить в HTML с использованием шаблона Django.
class Node():
name = "node name"
children = []
Будет существовать некоторый объект root
, который является Node
, а children
- список Node
s. root
будет передаваться в содержимом шаблона.
Я нашел это одно обсуждение того, как это может быть достигнуто, но плакат подсказывает, что это может быть нехорошо в производственной среде.
Знает ли кто-нибудь лучший способ?
Ответы
Ответ 1
Я думаю, что канонический ответ: "Не надо".
То, что вы, вероятно, должны делать, это разгадать вещь в вашем коде зрения, так что это просто вопрос итерации (в | де) вмятин в шаблоне. Я думаю, что я сделал бы это, добавив отступы и разделители в список, рекурсив через дерево, а затем отправив этот список "travelogue" в шаблон. (шаблон затем вставляет <li>
и </li>
из этого списка, создавая рекурсивную структуру с "пониманием" этого.)
Я также уверен, что рекурсивно, включая файлы шаблонов, это действительно неправильный способ сделать это...
Ответ 2
Используя тег шаблона 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>
Ответ 3
это может быть больше, чем вам нужно, но есть модуль django под названием "mptt" - он хранит иерархическую древовидную структуру в базе данных sql и включает в себя шаблоны для отображения в коде представления. вы могли бы найти там что-то полезное.
здесь ссылка: django-mptt
Ответ 4
Да, вы можете это сделать. Это небольшой трюк,
передав имя файла {% include%} в качестве переменной:
{% with template_name="file/to_include.html" %}
{% include template_name %}
{% endwith %}
Ответ 5
Django имеет встроенный помощник шаблона для этого точного сценария:
https://docs.djangoproject.com/en/dev/ref/templates/builtins/#unordered-list
Ответ 6
У меня была такая же проблема, и я написал тег шаблона. Я знаю, что есть другие теги, подобные этому, но мне нужно было научиться создавать пользовательские теги:) Я думаю, что все получилось очень хорошо.
Прочтите инструкцию docstring для использования.
github.com/skid/django-recurse
Ответ 7
Я слишком поздно)
Все вы используете так много ненужных тегов с, вот как я повторяю:
в основном шаблоне:
<!-- 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 %}
Ответ 8
Разве никто не любит диктовать? Возможно, я что-то пропустил, но это, пожалуй, самый естественный способ настройки меню. Использование ключей в качестве записей и значений, когда ссылки появляются в 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>
Он не пробовал по умолчанию или заказал, возможно, у вас есть?
Ответ 9
исправьте это:
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)
Ответ 10
У меня была аналогичная проблема, однако я сначала реализовал решение с использованием JavaScript, а сразу подумал, как бы я сделал то же самое в шаблонах django.
Я использовал утилиту serializer, чтобы превратить список из моделей в json, и использовал json-данные в качестве основы для моей иерархии.