A flexible menu builder for Wagtail CMS
Project description
Wagtail MenuBuilder
A flexible and easy-to-use menu management system for Wagtail CMS that allows you to create and manage menus directly from the Wagtail admin interface.
Features
- Create multiple menus with different slugs
- Hierarchical menu structure with unlimited depth
- Drag-and-drop menu item ordering
- Automatic page link updates when pages are moved
- Custom template support
- Built-in templates for common menu types (e.g., top navigation, footer)
- Wagtail 6.0+ compatible
Requirements
- Python 3.8+
- Django 4.2+
- Wagtail 6.0+
Installation
-
Install the package using pip:
pip install wagtail-menubuilder
-
Add
wagtail_menubuilderto yourINSTALLED_APPSinsettings.py:INSTALLED_APPS = [ ... 'wagtail.admin', 'wagtail.core', ... 'wagtail_menubuilder', ... ]
-
Run migrations:
python manage.py migrate wagtail_menubuilder
Quick Start
1. Creating and Managing Menus
- Access the Wagtail Admin Panel.
- Navigate to Snippets in the left sidebar.
- Click on Menubuilder.
- Click Add Menubuilder to create a new menu.
2. Menu Configuration
- Title: Give your menu a descriptive name (e.g., "Main Navigation", "Footer Menu").
- Slug: Use a unique identifier (e.g., "main-nav", "footer").
- Menu Items: Add and organize your menu items:
- Title: The text that appears in the menu.
- URL: External link (optional).
- Internal Link: Link to a Wagtail page (optional).
- Parent Item: Create dropdown menus by setting a parent.
Using Menus in Templates
Rendering Menus
-
Load the template tags in your template:
{% load menubuilder_tags %}
-
Render a menu using its slug:
{% render_menu "your-menu-slug" %}
Example: Using the top-navbar.html Template
The package includes an example template, wagtail_menubuilder/templates/menubuilder/top-navbar.html, which demonstrates a responsive navigation bar.
Note: This template is provided as a starting point. Its CSS and JavaScript are now in separate static files (wagtail_menubuilder/static/menubuilder/css/top-navbar.css and js/top-navbar.js) and should be included in your project's base template as shown below.
Steps to Use top-navbar.html:
-
Add the Template to Your Base Template
Load the required tags and render the menu in your global template (e.g.,
base.html):{% load static menubuilder_tags %} {% render_menu "top-navbar" %}
If your template uses Wagtail-specific features (e.g.,
{% pageurl %}), also loadwagtailcore_tags:{% load static wagtailcore_tags menubuilder_tags %}
-
Create a Template File Matching the Slug
The slug defined in the Menubuilder menu must match the name of the template file used to render it. For example:
- If the menu slug is
top-navbar, therender_menutag will look forwagtail_menubuilder/templates/menubuilder/top-navbar.html. You can override this by creating your owntemplates/wagtail_menubuilder/top-navbar.htmlin your project.
- If the menu slug is
-
Include Styles and Scripts
Ensure the required CSS and JavaScript files (provided with the package) are loaded in your base template (
base.html):{% load static %} ... <link rel="stylesheet" type="text/css" href="{% static 'menubuilder/css/top-navbar.css' %}"> ... <script type="text/javascript" src="{% static 'menubuilder/js/top-navbar.js' %}"></script> ...(Note: The paths assume your static files setup correctly collects files from
wagtail_menubuilder/static/) -
(Optional) Customize
top-navbar.html- If you need to modify the HTML structure, copy the template file from
wagtail_menubuilder/templates/menubuilder/top-navbar.htmlinto your project's template directory attemplates/wagtail_menubuilder/top-navbar.htmland edit it there. Django will automatically pick up your overridden version.
- If you need to modify the HTML structure, copy the template file from
Advanced Usage
Custom Menu Templates
You can create custom templates for your menus by using the following context variables:
menu: The menu object (instance ofMenu).visible_items: List of top-level menu item objects (instances ofMenuItem) that should be displayed (e.g., linked page is live, and if it was a parent, it has visible children). Each item object has avisible_childrenattribute containing a list of its processed child items.request: The current request object.
Example Custom Template
<nav class="custom-menu">
<ul>
{% for item in visible_items %} {# Use visible_items passed from the tag #}
<li class="{% if item.active %}active{% endif %}"> {# Note: 'active' class logic needs implementation based on request.path #}
<a href="{{ item.get_url }}">{{ item.title }}</a> {# Use get_url method #}
{% if item.visible_children %} {# Check for processed visible children #}
<ul class="submenu">
{% for child in item.visible_children %}
<li><a href="{{ child.get_url }}">{{ child.title }}</a></li> {# Use get_url method #}
{% endfor %}
</ul>
{% endif %}
</li>
{% endfor %}
</ul>
</nav>
Then use your custom template:
{% render_menu "main-menu" template="wagtail_menubuilder/custom-menu.html" %}
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- Fork the repository.
- Create your feature branch (
git checkout -b feature/AmazingFeature). - Commit your changes (
git commit -m 'Add some AmazingFeature'). - Push to the branch (
git push origin feature/AmazingFeature). - Open a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support This Project 💖
If you find this project helpful, consider supporting my work:
Your support helps me maintain and improve this project. Thank you! 🙏
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters