### Install wagtailmenus using pip
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/installation.rst
Use pip to install the wagtailmenus package. This is the first step in the installation process.
```console
pip install wagtailmenus
```
--------------------------------
### Set up Python virtual environment and install development dependencies
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/contributing/index.rst
Create a virtual environment and install wagtailmenus with development dependencies. This is the first step to setting up a local development environment.
```console
python3 -m venv .venv
pip install -e '.[development]' -U
source .venv/bin/activate
```
--------------------------------
### Install and update deployment dependencies
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/contributing/packaging_releases.rst
Ensure dependencies are up-to-date by installing the project in editable mode with deployment extras and upgrading.
```console
pip install -e '.[deployment]' -U
```
--------------------------------
### Flat Menu Template Structure Example (Multi-level)
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/rendering_menus/custom_templates.rst
Example directory structure for a flat menu with the handle 'info' that requires two levels of menu items. This demonstrates how to use specific templates for a particular flat menu.
```text
templates
└── menus
└── info
├── level_1.html # Used by the {% flat_menu %} tag for the 1st level
└── level_2.html # Used by the {% sub_menu %} tag for the 2nd level
```
--------------------------------
### Flat Menu Template Structure Example (Shared Templates)
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/rendering_menus/custom_templates.rst
Example of placing common templates in a shared folder for flat menus. This allows multiple flat menus to use the same template files, simplifying template management.
```text
templates
└── menus
└── flat
├── level_1.html
└── menu.html
```
--------------------------------
### Example Menu Structure
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/overview.rst
This illustrates a potential menu structure with nested items and specific configurations like allow_subnav and max_levels.
```none
├── Careers
├── Policies
└── Find an outlet
├── Bristol
├── Leicestershire
└── London
```
--------------------------------
### Main Menu Template Structure Example
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/rendering_menus/custom_templates.rst
Example directory structure for a multi-level main menu with three levels of links. This structure allows for custom templates for each level of the main menu.
```text
templates
└── menus
└── main
├── level_1.html # Used by {% main_menu %} for the 1st level
├── level_2.html # Used by {% sub_menu %} for the 2nd level
└── level_3.html # Used by {% sub_menu %} for the 3rd level
```
--------------------------------
### Install testing requirements
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/contributing/index.rst
Install the necessary packages for running the test suite. This includes dependencies required for testing wagtailmenus.
```console
source .venv/bin/activate
pip install -e '.[testing]' -U
```
--------------------------------
### Copy manage.py
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/contributing/index.rst
Create the manage.py file by copying its example. This file is essential for running Django management commands.
```console
cp manage.py{.example,}
```
--------------------------------
### Copy development settings
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/contributing/index.rst
Create a local copy of the development settings file. This allows for modifications without affecting the original example file.
```console
cp wagtailmenus/settings/development.py{.example,}
```
--------------------------------
### Install Development Requirements and Docs
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/contributing/index.rst
Activate your virtual environment and install wagtailmenus in editable mode with documentation dependencies. This command is necessary for local development and documentation building.
```console
source .venv/bin/activate
pip install -e '.[docs]' -U
```
--------------------------------
### Simple Children Menu Template Example
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/rendering_menus/custom_templates.rst
Example directory structure for a single-level children menu. This template is used by the {% children_menu %} tag.
```text
templates
└── menus
└── children_menu.html
```
--------------------------------
### Simple Section Menu Template Example
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/rendering_menus/custom_templates.rst
Example directory structure for a single-level section menu. This template is used by the {% section_menu %} tag.
```text
templates
└── menus
└── section_menu.html
```
--------------------------------
### Section Menu Template Structure Example
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/rendering_menus/custom_templates.rst
Example directory structure for a multi-level section menu. These templates are used by the {% section_menu %} tag.
```text
templates
└── menus
└── section
├── level_1.html # Used by the {% section_menu %} tag for the 1st level
├── level_2.html # Used by the {% sub_menu %} tag for the 2nd level
└── level_3.html # Used by the {% sub_menu %} tag for the 3rd level
```
--------------------------------
### Children Menu Template Structure Example
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/rendering_menus/custom_templates.rst
Example directory structure for a multi-level children menu. These templates are used by the {% children_menu %} tag.
```text
templates
└── menus
└── children
├── level_1.html # Used by the {% children_menu %} tag for the 1st level
└── level_2.html # Used by the {% sub_menu %} tag for the 2nd level
```
--------------------------------
### Run the development server
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/contributing/index.rst
Start the Django development server to run the project locally. This allows you to view and interact with your changes.
```console
python manage.py runserver
```
--------------------------------
### Inline Sub-Menu Rendering Example
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/rendering_menus/template_tag_reference.rst
This example demonstrates how to render sub-menus inline by adding add_sub_menus_inline=True to the main_menu tag. This simplifies the template structure by removing the need for the {% sub_menu %} tag.
```html
{% load menu_tags %}
{% for item in menu_items %}
-
{{ item.text }}
{% if item.has_children_in_menu %}
{% include "menus/custom_sub_menu.html" with sub_menu_items=item.get_children_in_menu %}
{% endif %}
{% endfor %}
```
--------------------------------
### Main Menu Rendering Example
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/rendering_menus/template_tag_reference.rst
Renders a main menu with sub-menus. It iterates through menu items, displaying active classes and links. Sub-menus are rendered recursively if they exist.
```html
{% for item in menu_items %}
{{ item.text }}
{% if item.sub_menu %}
{% endif %}
{% endfor %}
```
--------------------------------
### Define Custom FlatMenu and FlatMenuItem Models
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/advanced_topics/custom_menu_classes.rst
Create custom models by subclassing AbstractFlatMenu and AbstractFlatMenuItem. This example demonstrates adding translated fields and custom panels.
```python
# appname/models.py
from django.db import models
from django.utils import translation
from django.utils.translation import gettext_lazy as _
from modelcluster.fields import ParentalKey
from wagtail.admin.edit_handlers import FieldPanel, MultiFieldPanel, PageChooserPanel
from wagtailmenus.conf import settings
from wagtailmenus.panels import FlatMenuItemsInlinePanel
from wagtailmenus.models import AbstractFlatMenu, AbstractFlatMenuItem
class TranslatedField(object):
"""
A class that can be used on models to return a 'field' in the
desired language, where there a multiple versions of a field to
cater for multiple languages (in this case, English, German & French)
"""
def __init__(self, en_field, de_field, fr_field):
self.en_field = en_field
self.de_field = de_field
self.fr_field = fr_field
def __get__(self, instance, owner):
active_language = translation.get_language()
if active_language == 'de':
return getattr(instance, self.de_field)
if active_language == 'fr':
return getattr(instance, self.fr_field)
return getattr(instance, self.en_field)
class TranslatedFlatMenu(AbstractFlatMenu):
heading_de = models.CharField(
verbose_name=_("heading (german)"),
max_length=255,
blank=True,
)
heading_fr = models.CharField(
verbose_name=_("heading (french)"),
max_length=255,
blank=True,
)
translated_heading = TranslatedField('heading', 'heading_de', 'heading_fr')
# Like pages, panels for menus are split into multiple tabs.
# To update the panels in the 'Content' tab, override 'content_panels'
# To update the panels in the 'Settings' tab, override 'settings_panels'
content_panels = (
MultiFieldPanel(
heading=_("Settings"),
children=(
FieldPanel("title"),
FieldPanel("site"),
FieldPanel("handle"),
)
),
MultiFieldPanel(
heading=_("Heading"),
children=(
FieldPanel("heading"),
FieldPanel("heading_de"),
FieldPanel("heading_fr"),
),
classname='collapsible'
),
FlatMenuItemsInlinePanel(),
)
class TranslatedFlatMenuItem(AbstractFlatMenuItem):
"""A custom menu item model to be used by ``TranslatedFlatMenu``"""
menu = ParentalKey(
TranslatedFlatMenu, # we can use the model from above
on_delete=models.CASCADE,
related_name=settings.FLAT_MENU_ITEMS_RELATED_NAME,
)
link_text_de = models.CharField(
verbose_name=_("link text (german)"),
max_length=255,
blank=True,
)
link_text_fr = models.CharField(
verbose_name=_("link text (french)"),
max_length=255,
blank=True,
)
translated_link_text = TranslatedField('link_text', 'link_text_de', 'link_text_fr')
@property
def menu_text(self):
"""Use `translated_link_text` instead of just `link_text`"""
return self.translated_link_text or getattr(
self.link_page,
settings.PAGE_FIELD_FOR_MENU_ITEM_TEXT,
self.link_page.title
)
```
--------------------------------
### Flat Menu Rendering Example
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/rendering_menus/template_tag_reference.rst
Renders a flat menu with specific configurations. It loads menu tags, then renders a flat menu with a handle 'footer', limiting to one level, disabling the menu heading, and enabling fallback to default site menus.
```html
{% load menu_tags %}
{% flat_menu 'footer' max_levels=1 show_menu_heading=False fall_back_to_default_site_menus=True %}
```
--------------------------------
### Flat Menu Template Structure Example (Single-level)
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/rendering_menus/custom_templates.rst
Simplified directory structure for a flat menu with the handle 'info' that only needs to display one level of menu items. This is a more concise way to handle simple flat menus.
```text
templates
└── menus
└── info.html
```
--------------------------------
### Example Page Tree Structure
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/overview.rst
Illustrates a typical Wagtail page tree structure, including pages that might be hidden from menus or inactive.
```none
Home
├── What we do
│ ├── Aiding and supporting
│ ├── Researching
│ └── Driving change
├── Latest news
│ ├── Article one (``show_in_menus=False``)
│ ├── Article two (``show_in_menus=False``)
│ └── Article three (``show_in_menus=False``)
├── Find an outlet
│ ├── Bristol
│ │ └── City Centre outlet (``show_in_menus=False``)
│ ├── Leicestershire
│ │ ├── Hinckley outlet (``show_in_menus=False``)
│ │ └── Leicester outlet (``show_in_menus=False``)
│ ├── London
│ │ ├── Camden outlet (``show_in_menus=False``)
│ │ └── Peckham outlet (``show_in_menus=False``)
│ └── Oxfordshire (``live=False``)
│ └── Oxford outlet (``show_in_menus=False``)
├── Get involved
│ ├── Local community groups
│ ├── Schools and young people
│ ├── Help as a company
│ └── Donate
├── Careers
│ ├── Vacancy one (``show_in_menus=False``)
│ └── Vacancy two (``show_in_menus=False``)
├── Policies
│ ├── Terms and conditions
│ ├── Cookie policy
│ └── Privacy policy
└── Contact us
```
--------------------------------
### Generated Menu Structure Example
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/overview.rst
Shows how Wagtailmenus generates a multi-level menu based on selected top-level items and page tree structure, respecting `show_in_menus` and `allow_subnav` settings.
```none
├── What we do
│ ├── Aiding and supporting
│ ├── Researching
│ └── Driving change
├── Get involved
│ ├── Local community groups
│ ├── Schools and young people
│ ├── Help as a company
│ └── Donate
├── Latest news
└── Donate
```
--------------------------------
### Section Menu Template Example
Source: https://github.com/jazzband/wagtailmenus/blob/master/wagtailmenus/templates/menus/section_menu.html
Renders a hierarchical menu based on menu_items. Includes optional display of a section root and recursively renders sub-menus.
```django
{% load menu_tags %} {% if menu_items %}
{% if show_section_root and section_root %} [{{ section_root.text }}]({{ section_root.href }}) {% endif %}
{% for item in menu_items %}* [{{ item.text }}]({{ item.href }}) {% if item.has_children_in_menu %} {% sub_menu item %} {% endif %}
{% endfor %}
{% endif %}
```
--------------------------------
### Define Custom Main Menu Item Model
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/advanced_topics/custom_menu_classes.rst
Example of a minimal custom main menu item model subclassing AbstractMainMenuItem. This is used when extending the main menu functionality.
```python
class CustomMainMenuItem(AbstractMainMenuItem):
pass
```
--------------------------------
### Define Custom Flat Menu Item Model with Extra Fields
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/advanced_topics/custom_menu_classes.rst
Example of a custom flat menu item model subclassing AbstractFlatMenuItem, adding image and hover description fields. This allows for richer menu item content.
```python
# apname/models.py
from django.db import models
from django.utils.translation import gettext_lazy as _
from modelcluster.fields import ParentalKey
from wagtail.images import get_image_model_string
from wagtail.images.edit_handlers import ImageChooserPanel
from wagtail.admin.edit_handlers import FieldPanel, PageChooserPanel
from wagtailmenus.models import AbstractFlatMenuItem
class CustomFlatMenuItem(AbstractFlatMenuItem):
"""A custom menu item model to be used by ``wagtailmenus.FlatMenu``"""
menu = ParentalKey(
'wagtailmenus.FlatMenu',
on_delete=models.CASCADE,
related_name="custom_menu_items", # important for step 3!
)
image = models.ForeignKey(
get_image_model_string(),
blank=True,
null=True,
on_delete=models.SET_NULL,
)
hover_description = models.CharField(
max_length=250,
blank=True
)
# Also override the panels attribute, so that the new fields appear
# in the admin interface
panels = (
PageChooserPanel('link_page'),
FieldPanel('link_url'),
FieldPanel('url_append'),
FieldPanel('link_text'),
ImageChooserPanel('image'),
FieldPanel('hover_description'),
FieldPanel('allow_subnav'),
)
```
--------------------------------
### Override Only Sub-Menu Templates
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/rendering_menus/custom_templates.rst
This example shows how to override the templates used for sub-menus, while keeping the default template for the top-level menu. It illustrates specifying multiple templates for different sub-menu levels.
```html
{% load menu_tags %}
{# Just override the sub menu templates #}
{% main_menu max_levels=3 sub_menu_templates="custom_menus/main_menu_sub.html, custom_menus/main_menu_sub_level_2.html" %}
```
--------------------------------
### Activate virtual environment and update local repository
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/contributing/packaging_releases.rst
Activate the project's virtual environment, change directory to the original repository, checkout master, and pull the latest changes.
```console
source .venv/bin/activate
cd ../path-to-original-repo
git checkout master
git pull
```
--------------------------------
### Navigate to the docs directory
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/contributing/packaging_releases.rst
Change the current directory to the 'docs' folder to perform documentation-related checks.
```console
cd docs
```
--------------------------------
### Build HTML documentation
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/contributing/packaging_releases.rst
Execute 'make html' to build the HTML version of the documentation and fix any errors reported by Sphinx.
```console
make html
```
--------------------------------
### Manipulate Submenu Items Example
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/menupage.rst
Override modify_submenu_items and has_submenu_items methods in a MenuPage model to customize sub-menu item generation.
```python
# appname/models.py
from wagtailmenus.models import MenuPage
class ContactPage(MenuPage):
# ... other fields and methods ...
def modify_submenu_items(self):
# Example: Add additional links below each ContactPage
return [
# Add your custom submenu items here
]
def has_submenu_items(self):
# Return True if this page should have submenu items
return True
```
--------------------------------
### Run database migrations
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/contributing/index.rst
Apply database migrations to set up the necessary tables for the project. This command is run after setting up the development environment.
```console
python manage.py migrate
```
--------------------------------
### Override Only Top-Level Menu Template
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/rendering_menus/custom_templates.rst
This example demonstrates how to override only the template used for the top-level menu items, leaving the sub-menu templates to their default.
```html
{% load menu_tags %}
{# Just override the top-level template #}
{% main_menu max_levels=3 template="custom_menus/main_menu.html" %}
```
--------------------------------
### Define Custom ChildrenMenu Class
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/advanced_topics/custom_menu_classes.rst
Subclass wagtailmenus.models.menus.ChildrenMenu to customize the queryset for children menus. This example includes draft and expired pages for superusers.
```python
# appname/menus.py
from django.utils.translation import gettext_lazy as _
from wagtail.core.models import Page
from wagtailmenus.models import ChildrenMenu
class CustomChildrenMenu(ChildrenMenu):
def get_base_page_queryset(self):
# Show draft and expired pages in menu for superusers
if self.request.user.is_superuser:
return Page.objects.filter(show_in_menus=True)
# Resort to default behaviour for everybody else
return super(CustomChildrenMenu, self).get_base_page_queryset()
```
--------------------------------
### Optional: Autopopulate main menus with home links
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/installation.rst
Use the 'autopopulate_main_menus' command with the '--add-home-links' option to include a link to the home page in the generated main menu.
```console
python manage.py autopopulate_main_menus --add-home-links
```
--------------------------------
### Override Sub-Menu Template with a Single Template
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/rendering_menus/custom_templates.rst
This example demonstrates overriding the sub-menu templates by specifying a single template file using the 'sub_menu_template' argument.
```html
{% load menu_tags %}
{# Just override the sub menu templates with a single template #}
{% main_menu max_levels=3 sub_menu_template="custom_menus/main_menu_sub.html" %}
```
--------------------------------
### Define Custom SectionMenu Class
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/advanced_topics/custom_menu_classes.rst
Subclass wagtailmenus.models.menus.SectionMenu to customize the queryset for section menus. This example shows how to include draft and expired pages for superusers.
```python
from django.utils.translation import gettext_lazy as _
from wagtail.core.models import Page
from wagtailmenus.models import SectionMenu
class CustomSectionMenu(SectionMenu):
def get_base_page_queryset(self):
# Show draft and expired pages in menu for superusers
if self.request.user.is_superuser:
return Page.objects.filter(show_in_menus=True)
# Resort to default behaviour for everybody else
return super(CustomSectionMenu, self).get_base_page_queryset()
```
--------------------------------
### Create a new branch for release preparation
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/contributing/packaging_releases.rst
Create a new branch from your master branch to prepare for the upcoming release.
```console
git checkout -b release-prep/2.X.X
```
--------------------------------
### Create and push new version tag
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/contributing/packaging_releases.rst
Create an annotated tag for the new version and push it to the remote repository. This action should trigger GitHub Actions to deploy to PyPI.
```console
git tag -a v2.X
git push --tags
```
--------------------------------
### Run Django migrations for wagtailmenus
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/installation.rst
Execute Django migrations to create the necessary database tables for wagtailmenus. This command should be run after updating settings.
```console
python manage.py migrate wagtailmenus
```
--------------------------------
### Optional: Autopopulate main menus
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/installation.rst
Use the 'autopopulate_main_menus' command to populate main menus based on your site's page structure. This is a one-time command.
```console
python manage.py autopopulate_main_menus
```
--------------------------------
### Run the test suite
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/contributing/index.rst
Execute all unit tests for wagtailmenus. This command verifies that your code changes have not introduced any regressions.
```console
python runtests.py
```
--------------------------------
### Children Menu with Template and Sub-menu Templates
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/rendering_menus/template_tag_reference.rst
Demonstrates how to use the `children_menu` tag with `max_levels`, `template`, and `sub_menu_templates` arguments to control menu rendering and sub-menu levels.
```html
{% load menu_tags %}
{% children_menu max_levels=3 template="level_1.html" sub_menu_templates="level_2.html, level_3.html" %}
```
--------------------------------
### Create a superuser
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/contributing/index.rst
Create a superuser account to access the Django admin interface. This is necessary for managing content and settings.
```console
python manage.py createsuperuser
```
--------------------------------
### Specify Custom Templates for Main Menu and Sub-Menus
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/rendering_menus/custom_templates.rst
Use the 'template' and 'sub_menu_templates' arguments to explicitly define custom HTML files for rendering the main menu and its sub-menus. The 'sub_menu_templates' argument accepts a comma-separated list of templates for different sub-menu levels.
```html
{% load menu_tags %}
{% main_menu max_levels=3 template="custom_menus/main_menu.html" sub_menu_templates="custom_menus/main_menu_sub.html, custom_menus/main_menu_sub_level_2.html" %}
```
--------------------------------
### Copy development URLs
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/contributing/index.rst
Create a local copy of the development URLs file. This is necessary for configuring the project's URL routing during development.
```console
cp wagtailmenus/development/urls.py{.example,}
```
--------------------------------
### Implement MenuPageMixin with Custom Settings
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/menupage.rst
Subclass MenuPageMixin and override settings_panels to include custom fields and menupage_panel, excluding default Wagtail settings.
```python
from wagtail.contrib.forms.models import AbstractEmailForm
from wagtailmenus.models import MenuPageMixin
from wagtailmenus.panels import menupage_panel
from wagtail.admin.edit_handlers import FieldPanel
class MyEmailFormPage(AbstractEmailForm, MenuPageMixin):
"""This page will gain the same fields and methods as if it extended
`wagtailmenus.models.MenuPage`"""
...
settings_panels = [
FieldPanel('custom_settings_field_one'),
FieldPanel('custom_settings_field_two'),
menupage_panel
]
...
```
--------------------------------
### Organizing Custom Templates in Root Menus Folder (Using includes)
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/rendering_menus/custom_templates.rst
This structure moves custom templates for specific menus ('info' and 'contact') to the root 'menus' folder, using {% includes %} to reference the base flat templates. This further simplifies template organization and discoverability.
```text
templates
└── menus
├── flat
│ │ # Still used by default (e.g. for menus with different handles)
│ ├── level_1.html
│ ├── level_2.html
│ └── level_3.html
├── info
│ │ # This location is still preferred when rendering an 'info' menu
│ ├── level_1.html # {% includes 'menus/flat/level_1.html' %}
│ └── level_2.html # Our custom template from before
└── contact
│ # This location is still preferred when rendering a 'contact' menu
├── level_1.html # Our custom template from before
└── level_2.html # {% includes 'menus/flat/level_2.html' %}
```
--------------------------------
### Run tests with coverage report
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/contributing/index.rst
Execute unit tests and generate a code coverage report. This helps identify which parts of your code are not being tested.
```console
coverage run --source=wagtailmenus runtests.py
coverage report
```
--------------------------------
### Main Menu with Custom Sub-Menu Templates
Source: https://github.com/jazzband/wagtailmenus/blob/master/wagtailmenus/tests/templates/base.html
Renders the main menu with custom templates specified for sub-menu levels 2 and 3.
```html
{% main_menu max_levels=3 sub_menu_templates='menus/sub_menu_level_2.html, menus/sub_menu_level_3.html' %}
```
--------------------------------
### Initialize Workflow in Wagtail Menus
Source: https://github.com/jazzband/wagtailmenus/blob/master/wagtailmenus/templates/wagtailmenus/mainmenu_edit.html
This snippet includes the necessary template for initializing workflow features within the Wagtail admin interface, if a workflow is enabled.
```html
{% if workflow_enabled %} {% include "wagtailadmin/shared/_workflow_init.html" %} {% endif %}
```
--------------------------------
### Main Menu with Max Levels Set to 2
Source: https://github.com/jazzband/wagtailmenus/blob/master/wagtailmenus/tests/templates/base.html
Renders the main menu, limiting the display to a maximum of 2 levels.
```html
{% main_menu max_levels=2 %}
```
--------------------------------
### Flat Menu for Non-existent Menu
Source: https://github.com/jazzband/wagtailmenus/blob/master/wagtailmenus/tests/templates/base.html
Attempts to render a flat menu with a name that does not exist.
```html
{% flat_menu 'made-up-menu' %}
```
--------------------------------
### Main Menu with Absolute Page URLs Enabled
Source: https://github.com/jazzband/wagtailmenus/blob/master/wagtailmenus/tests/templates/base.html
Renders the main menu using absolute URLs for page links.
```html
{% main_menu use_absolute_page_urls=True %}
```
--------------------------------
### Configure Wagtailmenus to Use Custom Main Menu Model
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/advanced_topics/custom_menu_classes.rst
Project setting to specify the custom main menu model to be used by wagtailmenus.
```python
# e.g. settings/base.py
WAGTAILMENUS_MAIN_MENU_MODEL = "appname.LimitedMainMenu"
```
--------------------------------
### Main Menu with Max Levels Set to 3
Source: https://github.com/jazzband/wagtailmenus/blob/master/wagtailmenus/tests/templates/base.html
Renders the main menu, limiting the display to a maximum of 3 levels.
```html
{% main_menu max_levels=3 %}
```
--------------------------------
### Implementing MenuPage with an abstract base model
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/menupage.rst
If you use an abstract base model for common functionality, update it to subclass MenuPage. Then, other models can inherit from this updated base model.
```python
# appname/models.py
from wagtailmenus.models import MenuPage
class BaseProjectPage(MenuPage):
...
class GenericPage(BaseProjectPage):
...
class ContactPage(BaseProjectPage):
...
```
--------------------------------
### Overriding Templates for Specific Menus (Method 1)
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/rendering_menus/custom_templates.rst
This structure demonstrates overriding templates for specific menus ('info' and 'contact') by placing custom templates within subdirectories of the default menu template path. The system prefers these more specific paths.
```text
templates
└── menus
└── flat
├── level_1.html
├── level_2.html
├── level_3.html
├── info
│ │ # This location is preferred when rendering an 'info' menu
│ └── level_2.html # Only override the level 2 template
└── contact
│ # This location is preferred when rendering a 'contact' menu
└── level_1.html # Only override the level 1 template
```
--------------------------------
### Configuring Sub Menu Templates
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/rendering_menus/template_tag_reference.rst
Specifies multiple templates for rendering different levels of sub-menus. 'level_1.html' is used for the first level, 'level_2.html' for the second, and 'level_3.html' for the third.
```html
{% load menu_tags %}
{% main_menu max_levels=3 template="level_1.html" sub_menu_templates="level_2.html, level_3.html" %}
```
--------------------------------
### Run Multi-Environment Tests with Tox
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/contributing/index.rst
Execute all configured test environments for wagtailmenus using the tox command. This ensures compatibility across different Python versions and dependencies.
```console
tox
```
--------------------------------
### Implement MenuPageMixin with Wagtail Settings
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/menupage.rst
Subclass MenuPageMixin and include menupage_settings_panels to retain Wagtail's default settings fields along with wagtailmenus fields.
```python
from wagtail.contrib.forms.models import AbstractEmailForm
from wagtailmenus.models import MenuPageMixin
from wagtailmenus.panels import menupage_settings_panels
class MyEmailFormPage(AbstractEmailForm, MenuPageMixin):
"""This page will gain the same fields and methods as if it extended
`wagtailmenus.models.MenuPage`"""
...
settings_panels = menupage_settings_panels
...
```
--------------------------------
### Implementing MenuPage
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/menupage.rst
Subclass wagtailmenus.models.MenuPage on your model instead of the usual wagtail.core.models.Page. This model will gain the fields, methods and 'setting_panels' attribute from MenuPage.
```python
# appname/models.py
from wagtailmenus.models import MenuPage
class GenericPage(MenuPage):
"""
This model will gain the fields, methods and 'setting_panels' attribute
from MenuPage.
"""
...
```
--------------------------------
### Flat Menu with Absolute Page URLs
Source: https://github.com/jazzband/wagtailmenus/blob/master/wagtailmenus/tests/templates/base.html
Renders a flat menu using absolute URLs for page links.
```html
{% flat_menu 'footer' use_absolute_page_urls=True %}
```
--------------------------------
### Overriding Templates for Specific Menus (Method 2 - Using extends)
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/rendering_menus/custom_templates.rst
This improved structure organizes custom templates for specific menus ('info' and 'contact') within subdirectories, using {% extends %} to inherit from the base flat templates. This makes it easier to identify custom templates.
```text
templates
└── menus
└── flat
│ # Still used by default (e.g. for menus with different handles)
├── level_1.html
├── level_2.html
├── level_3.html
├── info
│ │ # This location is preferred when rendering an 'info' menu
│ ├── level_1.html # {% extends 'menus/flat/level_1.html' %}
│ └── level_2.html # Our custom template from before
└── contact
│ # This location is preferred when rendering a 'contact' menu
├── level_1.html # Our custom template from before
└── level_2.html # {% extends 'menus/flat/level_2.html' %}
```
--------------------------------
### Render Flat Menu
Source: https://github.com/jazzband/wagtailmenus/blob/master/wagtailmenus/tests/templates/typical-page.html
Renders a flat menu with a specified name. 'show_multiple_levels' and 'max_levels' can be used to control its display.
```html
{% flat_menu 'header-secondary' show_multiple_levels=True max_levels=2 %}
```
--------------------------------
### Define Custom MainMenu and MainMenuItem Models
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/advanced_topics/custom_menu_classes.rst
Subclass both AbstractMainMenu and AbstractMainMenuItem to create custom models for both menu and menu items, allowing for extended functionality in both.
```python
# appname/models.py
from django.db import models
from django.utils import translation
from django.utils.translation import gettext_lazy as _
from django.utils import timezone
from modelcluster.fields import ParentalKey
from wagtail.admin.edit_handlers import FieldPanel, MultiFieldPanel, PageChooserPanel
from wagtailmenus.conf import settings
from wagtailmenus.models import AbstractMainMenu, AbstractMainMenuItem
class LimitedMainMenu(AbstractMainMenu):
limit_from = models.TimeField()
limit_to = models.TimeField()
def get_base_page_queryset(self):
"""
If the current time is between 'limit_from' and 'limit_to',
only surface pages that are owned by the logged in user
"""
if(
self.request.user and
self.limit_from < timezone.now() < self.limit_to
):
pass # Placeholder for actual logic
```
--------------------------------
### Render Menu Items and Sub-menus
Source: https://github.com/jazzband/wagtailmenus/blob/master/wagtailmenus/templates/menus/children_menu.html
This snippet shows how to load menu tags, check if menu items exist, and iterate through them. It displays each item's text and link, and recursively calls `sub_menu` for items with children.
```django
{% load menu_tags %} {% if menu_items %}
{% for item in menu_items %}* [{{ item.text }}]({{ item.href }}) {% if item.has_children_in_menu %} {% sub_menu item %} {% endif %}
{% endfor %}
{% endif %}
```
--------------------------------
### Flat Menu with Custom Templates
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/rendering_menus/template_tag_reference.rst
Renders a flat menu using specified templates for different levels. Use `template` for the top level and `sub_menu_templates` for subsequent levels.
```html
{% load menu_tags %}
{% flat_menu 'info' template="level_1.html" sub_menu_templates="level_2.html, level_3.html" %}
```
--------------------------------
### Specify Single Custom Template for All Sub-Menus
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/rendering_menus/custom_templates.rst
When only one template is needed for all sub-menu levels, you can provide a single template path to the 'sub_menu_templates' argument. Alternatively, the 'sub_menu_template' argument can be used for the same purpose, offering a slightly more verbose syntax.
```html
{% load menu_tags %}
{# A 'sub_menu_templates' value without commas is recognised as a single template #}
{% main_menu max_levels=3 template="custom_menus/main_menu.html" sub_menu_templates="custom_menus/main_menu_sub.html" %}
{# You can also use the 'sub_menu_template' (no plural) option, which is slightly more verbose #}
{% main_menu max_levels=3 template="custom_menus/main_menu.html" sub_menu_template="custom_menus/main_menu_sub.html" %}
```
--------------------------------
### Registering a hook as an ordinary function
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/advanced_topics/hooks.rst
Alternatively, you can register a hook by calling hooks.register directly, passing the hook name and the handler function. This is useful if the handler function is defined elsewhere.
```python
hooks.register('name_of_hook', my_hook_function)
```
--------------------------------
### Render Menu Items in Template
Source: https://github.com/jazzband/wagtailmenus/blob/master/wagtailmenus/tests/templates/menus/main/menu.html
Iterates through menu items and displays their text and href. Includes logic to render sub-menus if they exist.
```django
{% load menu_tags %}
{% for item in menu_items %}* [{{ item.text }}{% if item.has_children_in_menu %} {% endif %}]({{ item.href }}) {% if item.has_children_in_menu %} {% sub_menu item %} {% endif %}
{% endfor %}
```
--------------------------------
### Section Menu with Custom Templates and Max Levels
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/rendering_menus/template_tag_reference.rst
Renders a context-aware section menu. Specify the maximum number of levels to display and custom templates for the main menu and sub-menus.
```html
{% load menu_tags %}
{% section_menu max_levels=3 template="menus/custom_section_menu.html" sub_menu_template="menus/custom_section_sub_menu.html" %}
```
--------------------------------
### Generate Migrations
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/abstractlinkpage.rst
After defining your new page model, generate database migrations for your application using the Django management command.
```console
python manage.py makemigrations appname
```
--------------------------------
### Apply Migrations
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/abstractlinkpage.rst
Apply the newly created migrations to your database to update the schema for your custom page models.
```console
python manage.py migrate appname
```
--------------------------------
### HTML Output for Modified Menu Items
Source: https://github.com/jazzband/wagtailmenus/blob/master/docs/source/menupage.rst
Illustrates the resulting HTML structure when custom submenu items are added to a 'main_menu' for a 'ContactPage'.
```html
Contact us
```