### 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 %} ``` -------------------------------- ### 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 ```