Adding dynamic menus in Wagtail

Published on

I was experimenting with wagtail CMS (Content Management System) for quite some time for one of my projects. Wagtail is a Django based CMS, which providers powerful features to building a website. In this post I'm going to explain how we can build dynamic menus in the wagtail website.

Menus feature is not available with the wagtail. We can use wagtailmenus package to build dynamic menus. It provides various features to create dynamic menus.

Features

  • Menus with multi level menus
  • Static menus
  • Adding / Removing the menu items
  • link to Wagtail page, URL

Installation

  • We can install wagtail menus through pip.
pip install wagtailmenus

Configuration

  • Add following apps to the INSTALLED_APPS:
'wagtail.contrib.modeladmin',
'wagtailmenus',
  • Add context_processors in TEMPLATES configuration
'wagtailmenus.context_processors.wagtailmenus'
  • run migrations to apply wagtailmenus migrations.
python manage.py migrate wagtailmenus

Now two new options will be available under wagtail settings menu.

  • Main Menu - with different sub levels, There can be only one main menu for a website.
  • Flat Menu - without any sub levels, It can many flat menus and we can use it different parts of the page.

wagtail menu

wagtail menu

Adding menu items to main menu

  • Once the wagtailmenu is configured, you can login to the your wagtail project and configure the Main menu

    wagtail main menu

    wagtail main menu

  • you can add menu items directly here,

    Note: when you link a wagtail page, the show_in_menu should be enabled in page settings, otherwise it won't show up in your menu.

  • We need to load menu_tags in our templates to access the wagtail menu tags.

  • to include the menu, add {% main_menu template="home/main_menu.html" %}, here the template is where the actual menu is rendered, the sample code

{% load menu_tags %}
<div class="navbar">
{% for item in menu_items %}
<a href="{{ item.href }}">{{ item.text }}-{{item.has_children_in_menu}}</a>
{% endfor %}
</div>

How to use Flat Menu for our footer

  • Flat menus are similar to the main menu, but we can add as many menus we want
  • Menu Items are similar to main menu.
  • We can access flat menus using it's handle {% flat_menu privacy template="menus/custom_flat_menu.html" %}
  • To create a footer using the flat menu, I have created new template tag to filter to retrieve all footer menus.
from django import template
from django.template.defaultfilters import stringfilter
from wagtailmenus.models import FlatMenu
register = template.Library()

@register.simple_tag
def footer_menus():
return FlatMenu.objects.filter(handle__endswith='footer')

Note: the assumption here is all footer menu handle names ends with 'footer'.

  • we can now load footer_menus and access all menus ending with footer, and render each menu separately like below
{% footer_menus as menus %}
{% for menu in menus %}
<div class="col-md-4 {% if for.counter == 0 %} offset-md-4 {% endif %}">
<h4>{{menu.heading}}</h4>
{% flat_menu menu.handle template="home/footer_menu.html" %}
</div>
{% endfor %}
  • we can also extend the menu class and create our own menu for footer, but I opted for this approach, to keep it simple.

github link for working code: https://github.com/srkama/wagtailmenu-demo