Меню для django сайта
Как-то мне понадобилось реализовать меню на сайте, где пункты меню брались из базы данных.
На сайтах, которые я ранее писал на PHP это реализовывалось довольной легко, а вот на DJANGO я сразу не мог это реализовать. Самый топорный , это конечно же передавать пункты меню в шаблон в каждой вьюхе ))
Но погуглив , я понял, что это реализуется довольно легко с помощью пользовательских template tags.Но для новичков ,это вначале проблематично и поэтому это статья для них.
Создадим новый app
python manage.py startapp cms
В файле models.py создадим модель для Menu.
from django.db import models
class Menu(models.Model):
name = models.CharField('Название', max_length=100)
url = models.CharField('Ссылка', max_length=255)
position = models.PositiveIntegerField('Позиция', default=1)
def __str__(self):
return str(self.name)
class Meta:
ordering = ('position',)
verbose_name = 'Пункт меню'
verbose_name_plural = Пункты меню'
Внутри нашего приложения cms создадим папку templatetags. Внутри этой папки создайте пустой файл __init__.py
В папке templatetags создадим файл common_tags.py
from django import template
from cms.models import Menu
register = template.Library()
@register.inclusion_tag('menu.html', takes_context=True)
def show_top_menu(context):
menu_items = Menu.objects.all()
return {
"menu_items": menu_items,
}
Содержимое файла menu.html
<ul class="menu">
{% for m_item in menu_items %}
<li><a href="{{ m_item.url }}">{{ m_item.name }}</a></li>
{% endfor %}
</ul>
Мы создали наш шаблонный включаемый тег с названием show_top_menu с помощью метода inclusion_tag. Ему нужно передать в качестве параметра путь к файлу шаблона (в нашем случае menu.html), где будет html код. Туда мы можем передать пункты меню и другие параметры, которые нужно вывести.
Теперь мы можем в базовом шаблоне base.html включить этот наш шаблонный тэг с пунктами меню следующим образом.
{% load common_tags %}
# В нужном месте вставляете ваше меню
{% show_top_menu %}
Древовидное меню
Реализуем меню со вложенными пунктами. Пункты меню будем хранить в базе данных, чтобы можно было редактировать через административную панель.
Установим библиотеку django-mptt для работы с древовидными структурами
pip install django-mptt
Добавим эту либу в наш settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'mptt', #Добавляем django-mptt
'core',
]
Не забудьте создать с помощью startapp проект core , где мы будем хранить наши модели с пунктами меню.
Создаем модель в core/models.py , где будем хранить пункты меню.
from django.db import models
from mptt.models import MPTTModel, TreeForeignKey
class MenuItem(MPTTModel):
name = models.CharField(max_length=100, unique=True)
url = models.CharField('Ссылка', max_length=255)
position = models.PositiveIntegerField('Позиция', default=1)
parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')
class MPTTMeta:
order_insertion_by = ['position']
def __str__(self):
return str(self.name)
class Meta:
verbose_name = 'Пункт меню'
verbose_name_plural = 'Пункты меню'
Чтобы редактировать эти пункты в меню через админку мы файл core/admin.py добавим следующий код.
from django.contrib import admin
from mptt.admin import MPTTModelAdmin
from core.models import MenuItem
class MenuItemMPTTModelAdmin(MPTTModelAdmin):
mptt_level_indent = 20
admin.site.register(MenuItem, MenuItemMPTTModelAdmin)
Добавляем пункты меню через административную панель. Тут я корневым элементом сделал _root , чтобы пунктам верхнего меню можно было родителем указать этот элемент и который мы не будем выводить. А остальные пункты меню будут выводиться в меню.
Добавим show_menu в файл core/templatetags/common_tags.py
from django import template
from core.models import MenuItem
register = template.Library()
@register.inclusion_tag('templatetags/menu.html', takes_context=True)
def show_menu(context):
menu_items = MenuItem.objects.filter(level=1)
return {
"menu_items": menu_items,
}
Добавим html код , где будет формироваться меню .Этот файл core/templates/templatetags/menu.html
Теперь в базовом шаблоне подключим наш inclusion_tag show_menu , где будет выводиться наше меню
Итого получим вот такой результат
Весь тестовый проект доступен на Github
Заключение
В данной статье бы показан как с помощью пользовательских шаблонных тегов выводить пункты меню. В частности для этого был использован метод inclusion_tag.
Если будут вопросы , то с радостью отвечу на них в комментариях