Cubane
1.0.11
  • Getting started
  • Topics
    • Resources
    • Fonts
    • SVG Icons
    • Media
    • Backend System
    • Content Management
      • Getting Started
      • Pages
      • Posts
      • Navigation
        • Navigation Sections
        • Navigation Item
        • Navigation Item Hierarchy
        • Navigation Item Posts
        • Navigation by Identifier
        • Navigation Builder
      • CMS System
      • Links
      • Sitemap
      • Legacy URLs
      • Cache
    • Enquiry Forms
    • Favourite Icon
    • Modules and Extensions
    • Settings
    • Deployment
    • Pulling Production Data
    • Testing Cubane
  • Cubane Reference
Cubane
  • Docs »
  • Topics »
  • Content Management »
  • Navigation
  • Edit on GitHub

Navigation¶

The CMS system provides a simple navigation system by which pages can be organised into one or more navigation sections. For example, any given page may appear in the header navigation, the footer navigation or both at the same time.

Navigation sections are declared in the following way as part of the application settings:

CMS_NAVIGATION = (
    ('header', 'Header'),
    ('footer', 'Footer'),
)

Navigation section are declared like choices where the first element declares the internal name of the navigation section and the second element declares the visual name of the navigation section that is presented to users in the backend system.

In the example above, two navigation sections are declared: One called Header and another one called Footer. Content editors can now assign pages to one of those navigation sections (or both).

As a consequence, the following structures are available in the template when rendering a page:

Template Variable Description
nav A structure that contains all navigation sections and navigation items per section.
pages A list of all pages that have a unique page identifier assigned.
active_nav The navigation item that is currently active.

The following sections discuss those aspects in more details.

Navigation Sections¶

The nav template variable contains all declared navigation sections by its internal name. For example, if we had declared the following navigation sections:

CMS_NAVIGATION = (
    ('header', 'Header'),
    ('footer', 'Footer'),
)

Then the following template would render a list of links for all pages that are assigned to the header navigation:

{% load cms_tags %}
<!DOCTYPE html>
<html>
    <body>
        {% if nav.header %}
            <ul class="nav">
                {% for item in nav.header %}
                    <li{% if item.active %} class="active"{% endif %}>
                        <a href="{{ item.url }}" title="{{ item.page_title }}">{{ item.title }}</a>
                    </li>
                {% endfor %}
            </ul>
        {% endif %}
    </body>
</html>

The same would work with the footer navigation respectively. The list contains navigation items where each item is derived from the underlying page.

See also

The navigation structure is constructed by a so called navigation builder, which can be altered, for example to control how navigation items are created. Please refer to section Navigation Builder for more information.

The order in which items are listed is the order in which the underlying pages are organised. The order for pages can be changed by content editors by using the backend system.

Therefore there is a specific order to pages across all navigation sections. By default, the order of items within each navigation section cannot be changed in isolation.

Navigation Item¶

A navigation item is representing most aspects of the underlying page including its title and its URL but does not contain all information that reassembles the underlying page such as page content.

Most noticeable, a navigation item has a page_title property which contains the exact title of the underlying page. In a similar way the property nav_title is referring to a shorthand name of the page that is specifically be used for the purpose of presenting the page within the concept of a navigation system. However, this field is optional and might be None or empty.

The property title simply returns the navigation title (nav_title) if a value has been provided for it; otherwise the page title is used instead.

The property active is True if the current page is the page that the navigation item is referring to.

See also

The construction of navigation items can be altered. Please refer to section Navigation Builder for more information.

Putting it all together, a good template for rendering navigation items for a specific section is the following:

{% if nav.header %}
    <ul class="nav">
        {% for item in nav.header %}
            <li{% if item.active %} class="active"{% endif %}>
                <a href="{{ item.url }}" title="{{ item.page_title }}">{{ item.title }}</a>
            </li>
        {% endfor %}
    </ul>
{% endif %}

Each list item has the css class active if the corresponding page is the current page. Further, the full page title is present via the title attribute but the visible name of the link might be an alternative navigation title if present.

Navigation Item Hierarchy¶

Pages can be organised within a hierarchy. Therefore a page can be a parent page of another page. By default this feature is disabled in order to keep everything very simple. Therefore by default there is only a number of pages next to each other without any hierarchy.

However, page hierarchy can be enabled in application settings via the PAGE_HIERARCHY settings variable:

PAGE_HIERARCHY = True

By enabling the page hierarchy feature, the backend allows content editors to arrange pages into a hierarchy by either choosing a specific parent page for each page or by using drag and drop to arrange pages into a hierarchy.

With page hierarchy enabled, the navigation system introduces a number of additional properties for each navigation item related to the child pages for each page:

children

List of all navigation items describing all direct child pages of the given parent navigation item. Each navigation item may represents its direct child element via its children property. Any given node contains all child pages regardless of its assignment to navigation sections.

nav_children

List of all navigation items describing all direct child pages of the given parent navigation item that also are assigned to the same navigation section. Each navigation item may represents its direct child element via its nav_children property.

active_child

True if any child navigation item is active (e.g. its active property is True).

Navigation Item Posts¶

A similar concept to page hierarchy is called Posts. A page hierarchy allows for an arbitrarily deeply formed tree based of pages. All nodes in the tree are of the same type (a page).

As described in section Pages, a page is derived from cubane.cms.models.PageAbstract.

You can think of a Post to be a specialised version of a Page. In fact, cubane.cms.models.Post is derived from cubane.cms.models.PageBase which is also the root class for pages.

There is a specific relationship between pages and posts: A page has many posts. Usually this means that the parent page is listing all posts that are assigned to the page.

When rendering the navigation for a site, posts can also be represented as children of any given page. This behaviour must be enabled via the CMS_NAVIGATION_INCLUDE_CHILD_PAGES settings variable:

CMS_NAVIGATION_INCLUDE_CHILD_PAGES = True

If enabled, each navigation item that are representing a page will contain the property posts which represents a list if all posts that are assigned to the corresponding page.

Navigation by Identifier¶

A unique identifier can be assigned to specific pages. For example, if you had a specific page that is presenting a map of some sort for example and you would want to link to that page, you could simply refer to the map page by its identifier:

{% if pages.map %}
    <a href="{{ pages.map.url }}" title="{{ pages.map.page_title }}">{{ pages.map.title }}</a>
{% endif %}

The CMS system will generate a navigation item for each page that has a unique identifier assigned to it. Such page does not necessarily need to be assigned to a navigation section.

The template variable pages contains a property for each page that has an identifier. For example, the identifier map would yield a property called map for the pages object, so that pages.map is referring to the navigation item that represents the map page.

Navigation Builder¶

Any Django app can extend the CMS navigation builder including yours. In fact some default apps that belong to Cubane are doing exactly that in order to extend the navigation system.

For example, the app cubane.ishop is extending the CMS navigation system to include shop categories as navigation items in order to make it possible to generate navigation structures based on product categories.

In the same way, your app can extend the navigation system too, for example to add additional information to each navigation item.

Simply declare a function with the name install_nav within the __init__.py file of your Django app and then call the method cubane.cms.nav.CMSNavigationBuilder.register_extension() passing in your own extension of the navigation builder.

def install_nav(nav):
    from myapp.nav import MyNavigationExtension
    return nav.register_extension(MyNavigationExtension)

This is a common pattern that is used throughout Cubane for extending various aspects if the core system.

See also

Please refer to section Modules and Extensions for more information about Cubane’s extension system.

The extension is simply derived from object and then overrides methods as required:

class MyNavigationExtension(object):
    def get_objects(self, objects):
        """
        Override: Include 'navigation_image'
        """
        objects = super(MyNavigationExtension, self).get_objects(objects)
        return objects.select_related('navigation_image')


    def get_nav_item(self, page, nav_name=None):
        """
        Override: Add additional properties to a navigation item.
        """
        item = super(MyNavigationExtension, self).get_nav_item(page, nav_name)
        item['navigation_image'] = page.navigation_image
        return item

The example demonstrates how an additional field is added to each navigation item (navigation_image) while the underlying query is also altered as well in order to avoid fetching images for each page individually.

Note

Be aware that your app might not be the only one who is extending the navigation system. Always use super() in order to play nice with others; otherwise you may end up preventing other apps from overriding methods.

Next Previous

© Copyright 2018, Cubane.org.

Built with Sphinx using a theme provided by Read the Docs.
[email protected] Cubane on GitHub Cubane on GitHub