CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-wagtailmenus

An app to help you manage menus in your Wagtail projects more consistently.

Overview
Eval results
Files

page-integration.mddocs/

Page Integration

Mixins and base classes for integrating Wagtail pages with the WagtailMenus system. These components enable pages to participate in navigation structures, control their menu behavior, and provide specialized page types for menu functionality.

Capabilities

Menu Page Mixin

A mixin class that adds menu-related functionality to any Wagtail page, providing settings and behavior for controlling how pages appear in menus.

class MenuPageMixin:
    """
    Mixin for pages with menu functionality.
    
    Adds menu-related fields and methods to control how pages
    participate in menu structures and navigation.
    """
    
    # Menu behavior fields
    repeat_in_subnav: models.BooleanField  # Whether to repeat in sub-navigation
    repeated_item_text: models.CharField   # Custom text for repeated items
    
    # Menu settings panels for admin
    menu_settings_panels: list
    
    def modify_submenu_items(
        self, menu_items, current_page, current_ancestor_ids, current_site,
        allow_repeating_parents, apply_active_classes, original_menu_tag,
        menu_instance=None, request=None, use_absolute_page_urls=False
    ):
        """
        Modify menu items for sub-menu display.
        
        Args:
            menu_items: List of menu items to modify
            current_page: The current page being viewed
            current_ancestor_ids: IDs of current page ancestors
            current_site: Current site object
            allow_repeating_parents (bool): Whether to show repeating parent items
            apply_active_classes (bool): Whether to apply active CSS classes
            original_menu_tag (str): Name of original menu tag ('main_menu', etc.)
            menu_instance: Menu instance calling this method
            request: HTTP request object
            use_absolute_page_urls (bool): Whether to use absolute URLs
            
        Returns:
            Modified menu items list
        """
        
    def has_submenu_items(self, current_page, allow_repeating_parents,
                         original_menu_tag, menu_instance=None, request=None):
        """
        Check if this page has items for sub-menu display.
        
        Args:
            current_page: The current page being viewed
            allow_repeating_parents (bool): Allow parent items in sub-menus
            current_site: Current site object
            check_for_children (bool): Whether to check for child pages
            
        Returns:
            bool: True if page has sub-menu items
        """

Menu Page

An abstract page class that combines MenuPageMixin with Wagtail's Page model, providing a complete base for pages that participate in menu systems.

class MenuPage(MenuPageMixin, Page):
    """
    Abstract page with menu functionality.
    
    Extends Wagtail's Page model with menu-related fields and methods.
    Use as a base class for pages that need menu integration.
    """
    
    class Meta:
        abstract = True

Link Page

An abstract page type specifically designed for menu items that link to external URLs or provide redirects.

class AbstractLinkPage:
    """
    Base class for link pages that redirect to external URLs.
    
    Provides functionality for pages that exist primarily to
    link to external resources or redirect to other locations.
    """
    
    link_url: str  # External URL to redirect to
    link_text: str  # Display text for the link
    
    def get_sitemap_urls(self, request=None):
        """
        Return empty list as link pages shouldn't appear in sitemaps.
        
        Args:
            request: HTTP request object
            
        Returns:
            list: Empty list (link pages not included in sitemaps)
        """
        
    def serve(self, request):
        """
        Serve a redirect to the external URL.
        
        Args:
            request: HTTP request object
            
        Returns:
            HttpResponseRedirect: Redirect to link_url
        """

Sub-Menu Template Mixin

A mixin for pages that need to define custom templates for their sub-menu rendering.

class DefinesSubMenuTemplatesMixin:
    """
    Mixin for sub-menu template handling.
    
    Allows pages to specify custom templates for rendering
    their sub-menus at different levels.
    """
    
    def get_sub_menu_template_names(self, current_level=1):
        """
        Get template names for sub-menu rendering at specific levels.
        
        Args:
            current_level (int): Current menu depth level
            
        Returns:
            list: Template names for sub-menu rendering
        """

Usage Examples

Creating Menu-Enabled Pages

from wagtailmenus.models import MenuPageMixin
from wagtail.models import Page
from wagtail.fields import RichTextField
from wagtail.admin.panels import FieldPanel

class CustomPage(MenuPageMixin, Page):
    """Custom page with menu functionality."""
    
    body = RichTextField()
    
    content_panels = Page.content_panels + [
        FieldPanel('body'),
    ]
    
    # Add menu settings to the settings tab
    settings_panels = Page.settings_panels + MenuPageMixin.menu_settings_panels

Using MenuPage Base Class

from wagtailmenus.models import MenuPage
from wagtail.fields import RichTextField
from wagtail.admin.panels import FieldPanel

class ArticlePage(MenuPage):
    """Article page with built-in menu functionality."""
    
    body = RichTextField()
    author = models.CharField(max_length=100)
    
    content_panels = Page.content_panels + [
        FieldPanel('body'),
        FieldPanel('author'),
    ]
    
    # menu_settings_panels are automatically included

Creating Link Pages

from wagtailmenus.models import AbstractLinkPage
from wagtail.models import Page
from wagtail.admin.panels import FieldPanel
from django.db import models

class ExternalLinkPage(AbstractLinkPage, Page):
    """Page that redirects to external URLs."""
    
    # Additional fields beyond AbstractLinkPage
    description = models.TextField(blank=True)
    
    content_panels = Page.content_panels + [
        FieldPanel('link_url'),
        FieldPanel('link_text'),
        FieldPanel('description'),
    ]
    
    def get_link_text(self):
        """Get display text for menu items."""
        return self.link_text or self.title

Customizing Menu Behavior

class SpecialPage(MenuPageMixin, Page):
    """Page with custom menu behavior."""
    
    def modify_submenu_behaviour(self, menu_items, current_page,
                               current_ancestor_ids, current_site,
                               check_for_children=True):
        """Custom sub-menu behavior."""
        
        # Add custom menu items
        custom_items = self.get_custom_menu_items()
        menu_items.extend(custom_items)
        
        # Filter items based on user permissions
        if hasattr(current_page, 'request'):
            user = getattr(current_page.request, 'user', None)
            if user and not user.is_staff:
                menu_items = [item for item in menu_items 
                            if not getattr(item, 'staff_only', False)]
        
        return menu_items
    
    def has_submenu_items(self, current_page, allow_repeating_parents=True,
                         current_site=None, check_for_children=True):
        """Check for custom sub-menu items."""
        
        # Always return True if we have custom items
        if self.get_custom_menu_items():
            return True
            
        # Otherwise use default behavior
        return super().has_submenu_items(
            current_page, allow_repeating_parents,
            current_site, check_for_children
        )

Working with Sub-Menu Templates

from wagtailmenus.models import DefinesSubMenuTemplatesMixin

class CategoryPage(DefinesSubMenuTemplatesMixin, MenuPageMixin, Page):
    """Page with custom sub-menu templates."""
    
    category_type = models.CharField(max_length=50, choices=[
        ('products', 'Products'),
        ('services', 'Services'),
        ('resources', 'Resources'),
    ])
    
    def get_sub_menu_template_names(self, current_level=1):
        """Return category-specific sub-menu templates."""
        
        templates = []
        
        if self.category_type == 'products':
            templates.append('menus/product_submenu.html')
        elif self.category_type == 'services':
            templates.append('menus/service_submenu.html')
            
        # Add level-specific templates
        templates.append(f'menus/submenu_level_{current_level}.html')
        templates.append('menus/submenu.html')  # Fallback
        
        return templates

Menu Integration in Templates

<!-- Check if current page supports menu functionality -->
{% if page.show_in_menus %}
    <nav class="page-navigation">
        {% children_menu parent_page=page max_levels=1 %}
    </nav>
{% endif %}

<!-- Show sub-navigation if page has menu items -->
{% if page.has_submenu_items %}
    <aside class="subnav">
        {% section_menu show_section_root=False %}
    </aside>
{% endif %}

Page Settings Configuration

# In your page models, configure menu settings
class MyPage(MenuPageMixin, Page):
    # ... other fields
    
    settings_panels = Page.settings_panels + [
        # Menu settings are added via MenuPageMixin.menu_settings_panels
        FieldPanel('show_in_menus'),
        FieldPanel('repeat_in_subnav'),
    ] + MenuPageMixin.menu_settings_panels

Types

# Page integration field types
class PageIntegrationTypes:
    show_in_menus: bool
    repeat_in_subnav: bool
    link_url: str
    link_text: str
    menu_settings_panels: list
    
# Method parameter and return types
class PageMethodTypes:
    menu_items: list
    current_page: 'Page'
    current_ancestor_ids: list[int]
    current_site: 'Site'
    check_for_children: bool
    allow_repeating_parents: bool
    current_level: int

Install with Tessl CLI

npx tessl i tessl/pypi-wagtailmenus

docs

administration.md

configuration.md

index.md

models.md

page-integration.md

template-tags.md

tile.json