Link Search Menu Expand Document

Создание многоуровнего меню

Для хранения древовидной структуры рубрик в БД мы будем использовать Nested Sets (Вложенные множества).

Реализовать данный метод в Django можно при помощи модуля MPTT

pip3 install django-mptt

Инструкция по установке

Создание дополнительное приложения в текущем проекте

В нашем тестовом проекте для целей тестирования мы создадим создадим новое приложение TestApp

python3 manage.py startapp testapp

После в файле settings.py добавим наше приложение в список приложений:

INSTALLED_APPS = [
# 	...
    'testapp.apps.TestappConfig',
]

Далее в корневом файле urls.py добавим путь:

urlpatterns = [
    path('test/', include('testapp.urls')),
]

Далее в папке нашего нового модуля testapp создадим файл urls.py

from django.urls import path
from .views import *
urlpatterns = [
    path('', test, name='test')
]

Далее в локальном views.py описываем контоллер-функцию:

from django.shortcuts import render

def test(request):
    return render(request, 'testapp/test.html')

И в папке templates/testapp создаем test.html в котором опичываем шаблон отображения.

Добавим в admins.py наше новое приложение:

from .models import Rubric
admin.site.register(Rubric)

Настройка модуля MPTT

  1. Добавим приложение MPTT в settings.py:
    INSTALLED_APPS = (
     'django.contrib.auth',
     # ...
     'mptt',
    )
    
  2. Добавим модель в models.py

     from django.db import models
     from mptt.models import MPTTModel, TreeForeignKey
    
     class Rubric(MPTTModel):
         name = models.CharField(max_length=50, unique=True)
         parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')
    
         def __str__(self):
             return self.name
    
         class MPTTMeta:
             order_insertion_by = ['name']
    
  3. Выполняем миграцию:
python3 manage.py makemigrations <your_app>
python3 manage.py migrate

Для тестирования вывода создадим простейший вывод в файле views.py:

from .models import Rubric

def test(request):
    return render(request, "testapp/test.html", {'rubrics': Rubric.objects.all()})

Далее добавляем вывод дерева в файл testapp/test.html

{% load mptt_tags %}
<ul>
    {% recursetree rubrics %}
        <li>
            {{ node.name }}
            {% if not node.is_leaf_node %}
                <ul class="children">
                    {{ children }}
                </ul>
            {% endif %}
        </li>
    {% endrecursetree %}
</ul>

Настройка визуального отображения MPTT в административной панели

Подробнее про визуальную настройку

Настройка отступов

Для добавления отступов в админке достаточно импортировать в admins.py класс:

from mptt.admin import MPTTModelAdmin

И наследовать его нашим основным класссом MPTT, например так:

admin.site.register(Rubric, MPTTModelAdmin)

Настрока связей с MPTT моделью

Если мы хотим создать модель связанную с MPTT моделью, то это можно сделать так:

class Article(models.Model):
    name = models.CharField(max_length=50)
    category = TreeForeignKey(Rubric, on_delete=models.PROTECT)

Здесь вместо обчного models.ForeignKey мы используем TreeForeignKey. Это необходимо для сохранения вложенности. Не забываем выполнить миграцию.

Визуальное редактирование структуры вложенности в админке (перетаскивание)

Для этого в admins.py:

from mptt.admin import DraggableMPTTAdmin

admin.site.register(
    Rubric,
    DraggableMPTTAdmin,
    list_display=(
        'tree_actions',
        'indented_title',
    ),
    list_display_links=(
        'indented_title',
    ),
)