User site navigation

There are four template tags for use in the templates that are connected to the menu:

To use any of these template tags, you need to have {% load menu_tags %} in your template before the line on which you call the template tag.

Note

Please note that menus live in the menus application, which though tightly coupled to the cms application exists independently of it. Menus are usable by any application, not just by django CMS.

show_menu

The show_menu tag renders the navigation of the current page. You can overwrite the appearance and the HTML if you add a menu/menu.html template to your project or edit the one provided with django CMS. show_menu takes six optional parameters: start_level, end_level, extra_inactive, extra_active, namespace and root_id.

The first two parameters, start_level (default=0) and end_level (default=100) specify from which level the navigation should be rendered and at which level it should stop. If you have home as a root node (i.e. level 0) and don’t want to display the root node(s), set start_level to 1.

The third parameter, extra_inactive (default=0), specifies how many levels of navigation should be displayed if a node is not a direct ancestor or descendant of the current active node.

The fourth parameter, extra_active (default=100), specifies how many levels of descendants of the currently active node should be displayed.

The fifth parameter, namespace, is currently not implemented.

The sixth parameter root_id specifies the id of the root node.

You can supply a template parameter to the tag.

Some Examples

Complete navigation (as a nested list):

{% load menu_tags %}
<ul>
    {% show_menu 0 100 100 100 %}
</ul>

Navigation with active tree (as a nested list):

<ul>
    {% show_menu 0 100 0 100 %}
</ul>

Navigation with only one active extra level:

<ul>
    {% show_menu 0 100 0 1 %}
</ul>

Level 1 navigation (as a nested list):

<ul>
    {% show_menu 1 %}
</ul>

Navigation with a custom template:

{% show_menu 0 100 100 100 "myapp/menu.html" %}

show_menu_below_id

If you have set an id in the advanced settings of a page, you can display the sub-menu of this page with a template tag. For example, we have a page called meta that is not displayed in the navigation and that has the id “meta”:

<ul>
    {% show_menu_below_id "meta" %}
</ul>

You can give it the same optional parameters as show_menu:

<ul>
    {% show_menu_below_id "meta" 0 100 100 100 "myapp/menu.html" %}
</ul>

Unlike show_menu, however, soft roots will not affect the menu when using show_menu_below_id.

show_sub_menu

Displays the sub menu of the current page (as a nested list).

The first argument, levels (default=100), specifies how many levels deep the sub menu should be displayed.

The second argument, root_level (default=None), specifies at what level, if any, the menu should have its root. For example, if root_level is 0 the menu will start at that level regardless of what level the current page is on.

The third argument, nephews (default=100), specifies how many levels of nephews (children of siblings) are shown.

Fourth argument, template (default=menu/sub_menu.html), is the template used by the tag; if you want to use a different template you must supply default values for root_level and nephews.

Examples:

<ul>
    {% show_sub_menu 1 %}
</ul>

Rooted at level 0:

<ul>
    {% show_sub_menu 1 0 %}
</ul>

Or with a custom template:

<ul>
    {% show_sub_menu 1 None 100 "myapp/submenu.html" %}
</ul>

show_breadcrumb

Show the breadcrumb navigation of the current page. The template for the HTML can be found at menu/breadcrumb.html.:

{% show_breadcrumb %}

Or with a custom template and only display level 2 or higher:

{% show_breadcrumb 2 "myapp/breadcrumb.html" %}

Usually, only pages visible in the navigation are shown in the breadcrumb. To include all pages in the breadcrumb, write:

{% show_breadcrumb 0 "menu/breadcrumb.html" 0 %}

If the current URL is not handled by the CMS or by a navigation extender, the current menu node can not be determined. In this case you may need to provide your own breadcrumb via the template. This is mostly needed for pages like login, logout and third-party apps. This can easily be accomplished by a block you overwrite in your templates.

For example in your base.html:

<ul>
    {% block breadcrumb %}
    {% show_breadcrumb %}
    {% endblock %}
<ul>

And then in your app template:

{% block breadcrumb %}
<li><a href="/">home</a></li>
<li>My current page</li>
{% endblock %}

Properties of Navigation Nodes in templates

{{ node.is_leaf_node }}

Is it the last in the tree? If true it doesn’t have any children.

{{ node.level }}

The level of the node. Starts at 0.

{{ node.menu_level }}

The level of the node from the root node of the menu. Starts at 0. If your menu starts at level 1 or you have a “soft root” (described in the next section) the first node would still have 0 as its menu_level.

{{ node.get_absolute_url }}

The absolute URL of the node, without any protocol, domain or port.

{{ node.title }}

The title in the current language of the node.

{{ node.selected }}

If true this node is the current one selected/active at this URL.

{{ node.ancestor }}

If true this node is an ancestor of the current selected node.

{{ node.sibling }}

If true this node is a sibling of the current selected node.

{{ node.descendant }}

If true this node is a descendant of the current selected node.

{{ node.soft_root }}

If true this node is a soft root. A page can be marked as a soft root in its ‘Advanced Settings’.

CMS menus

class cms.cms_menus.CMSMenu(renderer)

Subclass of menus.base.Menu. Its get_nodes() creates a list of NavigationNodes based on a site’s cms.models.pagemodel.Page objects.

get_menu_node_for_page_content(page_content: PageContent, preview_url: str | None = None, cut: bool = False) CMSNavigationNode

Transform a CMS page content object into a navigation node.

Parameters:
  • page – The page to transform.

  • languages – The list of the current language plus fallbacks used to render the menu.

  • preview_url – If given, serves as a “pattern” for a preview url with the assumption that “/0/” is replaced by the actual page content pk. Default is None.

  • cut – If True the parent_id is set to None. Default is False.

Returns:

A CMSNavigationNode instance.

get_nodes(request) list[NavigationNode]

Returns a list of NavigationNode objects representing the navigation nodes to be displayed in the menu. This method is performance-critical since the number of page content objects can be large.

Parameters:
  • self – The instance of the class.

  • request – The HTTP request object.

Returns:

A list of NavigationNode objects representing the navigation nodes.

Return type:

list[NavigationNode]

Note

  • The method retrieves the necessary data from the database to build the navigation nodes for the menu.

  • The behavior of the method depends on whether the edit mode or preview mode is active in the toolbar.

  • If either edit mode or preview mode is active, the method retrieves all current page content objects visible in the admin for the current page.

  • If neither edit mode nor preview mode is active, the method retrieves only public page content objects.

  • The retrieved page contents are filtered based on the specified languages, sorted by page path, and filtered by site.

  • Only specific fields of the page content objects are selected to optimize performance.

  • If either edit mode or preview mode is active, a preview URL is constructed for a “virtual” non-existing page content with id=0 to avoid too many calls to revert the admin URL.

  • The method includes a nested function for prefetching URLs and filling the URL cache.

  • The visibility of the page contents is further filtered based on authentication and permissions.

  • The homepage is determined based on the page contents and marked for cutting if necessary.

  • The menu node for each page content is created using the get_menu_node_for_page_content method of the instance.

  • The prefetch_urls function is called for each page content to fill the URL cache and provide necessary data for creating the menu node.

  • The select_lang method is used to filter the page contents based on the specified language preferences.

select_lang(page_contents: Iterable[PageContent]) Generator[PageContent, None, None]

Generator that returns only those page content objects passed that contain the first language present in the languages list.

class cms.cms_menus.NavExtender(renderer)
modify(request, nodes, namespace, root_id, post_cut, breadcrumb)

Modify the list of nodes.

Args:

request: The request object. nodes: List of NavigationNode instances. namespace: The namespace for the menu. root_id: ID of the root node. post_cut: Boolean indicating post-cut status. breadcrumb: Boolean indicating breadcrumb status.

class cms.cms_menus.SoftRootCutter(renderer)

A soft root is a page that acts as the root for a menu navigation tree.

Typically, this will be a page that is the root of a significant new section on your site.

When the soft root feature is enabled, the navigation menu for any page will start at the nearest soft root, rather than at the real root of the site’s page hierarchy.

This feature is useful when your site has deep page hierarchies (and therefore multiple levels in its navigation trees). In such a case, you usually don’t want to present site visitors with deep menus of nested items.

For example, you’re on the page -Introduction to Bleeding-?, so the menu might look like this:

  • School of Medicine
    • Medical Education

    • Departments
      • Department of Lorem Ipsum

      • Department of Donec Imperdiet

      • Department of Cras Eros

      • Department of Mediaeval Surgery
        • Theory

        • Cures

        • Bleeding
          • Introduction to Bleeding <this is the current page>

          • Bleeding - the scientific evidence

          • Cleaning up the mess

          • Cupping

          • Leaches

          • Maggots

        • Techniques

        • Instruments

      • Department of Curabitur a Purus

      • Department of Sed Accumsan

      • Department of Etiam

    • Research

    • Administration

    • Contact us

    • Impressum

which is frankly overwhelming.

By making “Department of Mediaeval Surgery” a soft root, the menu becomes much more manageable:

  • Department of Mediaeval Surgery
    • Theory

    • Cures
      • Bleeding
        • Introduction to Bleeding <current page>

        • Bleeding - the scientific evidence

        • Cleaning up the mess

      • Cupping

      • Leaches

      • Maggots

    • Techniques

    • Instruments

find_ancestors_and_remove_children(node, nodes)

Check ancestors of node for soft roots

modify(request, nodes, namespace, root_id, post_cut, breadcrumb)

Modify the list of nodes.

Args:

request: The request object. nodes: List of NavigationNode instances. namespace: The namespace for the menu. root_id: ID of the root node. post_cut: Boolean indicating post-cut status. breadcrumb: Boolean indicating breadcrumb status.

class cms.menu_bases.CMSAttachMenu(*args, **kwargs)

Base class that can be subclassed to allow your app to attach its own menus.

classmethod get_apphooks()

Returns a list of apphooks to which this CMSAttachMenu is attached.

Calling this does not produce DB queries.

classmethod get_instances()

Return a queryset of all CMS Page objects (in this case) that are currently using this CMSAttachMenu either directly as a navigation_extender, or, as part of an apphook.

Calling this does perform a DB query.