Навигация в Wagtail CMS

В этой статье я расскажу как создать простое меню в Wagtail. Wagtail, это CMS основанная на Django и создана компанией Torchbox.

В ней уже есть встроенная иерархическая структура которая позволит сделать меню динамическим. В официальной документации не говорится как сделать меню, но зато можно подсмотреть как это сделано в wagtaildemo проекте. Для начала давайте создадим свой демо проект.

Создание проекта в Wagtail

Вначале установим сам wagtail, предлагаю его установить в virtualenv, итак:

# активируем виртуальное окружение
source venv/demo/bin/activate

# устанавливаем wagtail cms
pip install wagtail

# создаём проект (аналог django-admin startproject)
wagtail start demo

cd demo

# создадим БД командой
python manage.py migrate

# создадим администратора нашего сайта
python manage.py createsuperuser

# запустим сервер
python manage.py runserver

После всех этих процедур в браузере увидим

а структура папок проекта будет после команды wagtail start demo будет иметь следующий вид

Меню сайта

Добавим блок меню в базовый шаблон demo/demo/templates/base.html

{% load static wagtailuserbar %}
{% load home_tags %}
...

{% block menu %}
    {% get_site_root as site_root %}
    {% top_menu parent=site_root calling_page=self %}
{% endblock %}

Здесь мы с помощью тега get_site_root (который мы потом напишем) получаем верхний уровень меню. И передаём root в качестве параметра в другой тег top_menu, вторым параметром в этот тег мы передадим саму страничку (для того чтобы подсветить текущую активную страницу в меню).

Самое время создать эти два тэга в demo/home/templatetags/demo_tags.py

from django import template

register = template.Library()


# получим корневую страницу сайта
@register.assignment_tag(takes_context=True)
def get_site_root(context):
    return context['request'].site.root_page


@register.inclusion_tag('home/tags/top_menu.html', takes_context=True)
def top_menu(context, parent, calling_page=None):
    # выберем все дочерние страницы
    # которые опубликованы у которых отмечена галочка в админке
    # что нужно показывать в меню
    menuitems = parent.get_children().live().in_menu()
    for menuitem in menuitems:
        # menuitem.show_dropdown = has_menu_children(menuitem)
        # выставляем признак активности страницы в пункте меню
        menuitem.active = (calling_page.url.startswith(menuitem.url)
                           if calling_page else False)
    return {
        'calling_page': calling_page,
        'menuitems': menuitems,
        'request': context['request'],
    }

Создадим шаблон для меню demo/home/tags/top_menu.html

{% load home_tags wagtailcore_tags %}
{% get_site_root as site_root %}
<ul>
    {# ссылка на домашнюю страницу (корневая страничка сайта) #}
    <li><a href="{% pageurl site_root %}" title="{{ site_root.title }}">
               {{ site_root.title }}
           </a>
     </li>
{# Строим меню из дочерних страничек от корня сайта #}
{# и добавим для стилей класс active чтобы подсветить текущую #}
    {% for menuitem in menuitems %}
            <li class="{% if menuitem.active %}active{% endif %}">
                <a href="{% pageurl menuitem %}">{{ menuitem.title }}</a>
            </li>
    {% endfor %}
</ul>


Теперь добавим несколько страничек в админке


У меня после добавления получилось так:


Не забываем ставить галочку напротив "Показывать в меню":


Вот так легко мы смогли вывести динамически меню.