Using hooks to modify menus

On loading, Wagtail will search for any app with the file wagtail_hooks.py and execute the contents. This provides a way to register your own functions to execute at certain points in Wagtail’s execution, such as when a Page object is saved or when the main menu is constructed.

Registering functions with a Wagtail hook is done through the @hooks.register decorator:

from wagtail.wagtailcore import hooks

@hooks.register('name_of_hook')
def my_hook_function(arg1, arg2...)
    # your code here

Alternatively, hooks.register can be called as an ordinary function, passing in the name of the hook and a handler function defined elsewhere:

hooks.register('name_of_hook', my_hook_function)

Wagtailmenus utilises this same ‘hooks’ mechanism to allow you make modifications to menus at certain points during the rendering process.

Hooks for modifying QuerySets

When a menu instance is gathering the data it needs to render itself, it typically uses one or more QuerySets to fetch Page and MenuItem data from the database. These hooks allow you to modify those QuerySets before they are evaluated, allowing you to efficiently control menu contents.

If you need to override a lot of menu class behaviour, and you’re comfortable with the idea of subclassing the existing classes and models to override the necessary methods, you might want to look at Using custom menu classes and models. But, if all you want to do is change the result of a menu’s get_base_page_queryset() or get_base_menuitem_queryset() (say, to limit the links that appear based on the permissions of the currently logged-in user), you may find it quicker & easier to use the following hooks instead.

Hooks for modifying menu items

While the above tags are concerned with modifying the data used in a menu, the following hooks are called later on in the rendering process, and allow you to modify the list of MenuItem or Page objects before they are sent to a template to be rendered.

There are two hooks you can use to modify menu items, which are called at different stages of preparation.

Argument reference

In the above examples, **kwargs is used in hook method signatures to make them accepting of other keyword arguments, without having to declare every single argument that should be passed in. Using this approach helps create leaner, tidier code, and also makes it more ‘future-proof’, since the methods will automatically accept any new arguments that may be added by wagtailmenus in future releases.

Below is a full list of the additional arguments that are passed to methods using the above hooks:

request

The HttpRequest instance that the menu is currently being rendered for.

parent_context

The Context instance that the menu is being rendered from.

parent_page

If the menu being rendered is showing ‘children’ of a specific page, this will be the Page instance who’s children pages are being displayed. The value might also be None if no parent page is involved. For example, if rendering the top level items of a main or flat menu.

menu_tag

The name of the tag that was called to render the current part of the menu. If rendering the first level of a menu, this will have the same value as original_menu_tag. If not, it will have the value ‘sub_menu’ (unless you’re using custom tags that pass a different ‘tag_name’ value to the menu class’s ‘render_from_tag’ method)

original_menu_tag

The name of the tag that was called to initiate rendering of the menu that is currently being rendered. For example, if you’re using the main_menu tag to render a multi-level main menu, even though sub_menu may be called to render subsequent additional levels, ‘original_menu_tag’ should retain the value 'main_menu'. Should be one of: 'main_menu', 'flat_menu', 'section_menu' or 'children_menu'. Comparable to the menu_type values supplied to other hooks.

menu_instance

The menu instance that is supplying the data required to generate the current menu. This could be an instance of a model class, like MainMenu or FlatMenu, or a standard python class like ChildrenMenu or SectionMenu.

original_menu_instance

The menu instance that is supplying the data required to generate the current menu. This could be an instance of a model class, like MainMenu or FlatMenu, or a standard python class like ChildrenMenu or SectionMenu.

current_level

An integer value indicating the ‘level’ or ‘depth’ that is currently being rendered in the process of rendering a multi-level menu. This will start at 1 for the first/top-level items of a menu, and increment by 1 for each additional level.

max_levels

An integer value indicating the maximum number of levels that should be rendered for the current menu. This will either have been specified by the developer using the max_levels argument of a menu tag, or might have been set in the CMS for a specific MainMenu or FlatMenu instance.

current_site

A Wagtail Site instance, indicating the site that the current request is for (usually also available as request.site)

current_page

A Wagtail Page instance, indicating what wagtailmenus believes to be the page that is currently being viewed / requested by a user. This might be None if you’re using additional views in your project to provide functionality at URLs that don’t map to a Page in Wagtail.

current_page_ancestor_ids

A list of ids of Page instances that are an ‘ancestor’ of current_page.

current_section_root_page

If current_page has a value, this will be the top-most ancestor of that page, from just below the site’s root page. For example, if your page tree looked like the following:

Home (Set as 'root page' for the site)
├── About us
├── What we do
├── Careers
|   ├── Vacancy one
|   └── Vacancy two
├── News & events
|   ├── News
|   |   ├── Article one
|   |   └── Article two
|   └── Events
└── Contact us

If the current page was ‘Vacancy one’, the section root page would be ‘Careers’. Or, if the current page was ‘Article one’, the section root page would be ‘News & events’.

use_specific

An integer value indicating the preferred policy for using PageQuerySet.specific() and Page.specific in rendering the current menu. For more information see: ‘Specific’ pages and menus.

allow_repeating_parents

A boolean value indicating the preferred policy for having pages that subclass MenuPageMixin add a repeated versions of themselves to it’s children pages (when rendering a sub_menu for that page). For more information see: The MenuPage and MenuPageMixin models.

apply_active_classes

A boolean value indicating the preferred policy for setting active_class attributes on menu items for the current menu.

use_absolute_page_urls

A boolean value indicating the preferred policy for using full/absolute page URLs for menu items representing pages (observed by prime_menu_items() when setting the href attribute on each menu item). In most cases this will be False, as the default behaviour is to use ‘relative’ URLs for pages.