Создать гибкую систему меню в Django
Чтобы создать гибкую систему меню, похожую на WordPress, вам нужно реализовать модели для меню и пунктов меню, с возможностью динамического выбора URL-адресов для каждой страницы, категории или записи блога. Вот шаги, которые помогут вам это сделать.
1. Создайте модели для меню и пунктов меню
Начнем с создания двух моделей: Menu
для хранения основного меню и MenuItem
для пунктов меню, которые могут ссылаться на страницы, категории или посты блога.
# app/models.py
from django.db import models
from django.urls import reverse
class Menu(models.Model):
name = models.CharField("Название меню", max_length=100, unique=True)
def __str__(self):
return self.name
class MenuItem(models.Model):
menu = models.ForeignKey(Menu, related_name="items", on_delete=models.CASCADE)
title = models.CharField("Заголовок", max_length=100)
url = models.CharField("URL", max_length=255, blank=True, help_text="URL или выбрать страницу, категорию, пост")
page = models.ForeignKey('Page', blank=True, null=True, on_delete=models.SET_NULL, help_text="Выберите страницу")
blog_category = models.ForeignKey('BlogCategory', blank=True, null=True, on_delete=models.SET_NULL, help_text="Выберите категорию блога")
blog_post = models.ForeignKey('BlogPost', blank=True, null=True, on_delete=models.SET_NULL, help_text="Выберите пост блога")
order = models.PositiveIntegerField("Порядок", default=0)
class Meta:
ordering = ['order']
def save(self, *args, **kwargs):
# Приоритет URL, если он указан вручную
if not self.url:
if self.page:
self.url = reverse('page_detail', args=[self.page.slug])
elif self.blog_category:
self.url = reverse('blog_category_detail', args=[self.blog_category.slug])
elif self.blog_post:
self.url = reverse('blog_post_detail', args=[self.blog_post.slug])
super().save(*args, **kwargs)
def __str__(self):
return self.title
2. Зарегистрируйте модели в админпанели
Настроим админпанель, чтобы можно было добавлять пункты меню к каждому меню в виде inline-элементов. Это позволит вам организовать иерархию и порядок меню.
# app/admin.py
from django.contrib import admin
from .models import Menu, MenuItem
class MenuItemInline(admin.TabularInline):
model = MenuItem
extra = 1
@admin.register(Menu)
class MenuAdmin(admin.ModelAdmin):
inlines = [MenuItemInline]
list_display = ("name",)
3. Настройте маршруты (urls.py)
Убедитесь, что у вас есть соответствующие URL-шаблоны для страниц, категорий и постов, которые соответствуют именам в reverse
. Например:
# app/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('page/<slug:slug>/', views.page_detail, name='page_detail'),
path('blog/category/<slug:slug>/', views.blog_category_detail, name='blog_category_detail'),
path('blog/post/<slug:slug>/', views.blog_post_detail, name='blog_post_detail'),
]
4. Создайте представление для получения меню
Добавьте в представления функцию, которая будет извлекать меню по имени и передавать его в шаблон.
# app/views.py
from django.shortcuts import render, get_object_or_404
from .models import Menu
def get_menu(name):
return get_object_or_404(Menu, name=name)
5. Выведите меню в шаблоне
Теперь можно динамически выводить меню в любом шаблоне, используя имя меню для загрузки его элементов.
- Создайте включаемый шаблон для меню, например,
menu.html
:
<!-- templates/menu.html -->
<ul>
{% for item in menu.items.all %}
<li><a href="{{ item.url }}">{{ item.title }}</a></li>
{% endfor %}
</ul>
2. Включите меню в нужный шаблон и передайте его через представление.
В представлении можно передать меню в контекст:
def some_view(request):
menu = get_menu('Main Menu') # Замените 'Main Menu' на имя меню
return render(request, 'some_template.html', {'menu': menu})
3. В some_template.html
вставьте меню:
{% include 'menu.html' with menu=menu %}
6. Подключите меню к любым шаблонам
Добавьте вызов меню в нужных шаблонах. Например, если меню должно отображаться на всех страницах, его можно добавить в базовый шаблон.
Теперь вы можете добавлять, редактировать и организовывать меню и пункты меню в админпанели, а также динамически выводить их в шаблонах.
Отправить комментарий
Для отправки комментария вам необходимо авторизоваться.