PloneDocumentation
  • Documentation
  • Developing for Plone
  • Programming Plone
  • Miscellaneous information
  • Navigation trees
  • Previous
  • Next

Warning

This version is valid for an outdated version of Plone: 4.X. Use the Version drop-down above to go to the Plone 6 or Plone 5 versions

  • Introduction
  • Quickstart
  • Working with Content
  • Adapting & Extending Plone
  • Installing, Managing and Updating Plone
  • Developing for Plone
    • Developing add-ons
    • Programming with Plone
      • Programming Plone
        • Getting started
        • HTTP serving and traversing site data
        • Views, viewlets and layers
        • Content management
        • Models, forms, fields and widgets
        • ZODB, persistency and transactions
        • Functionality and features
        • Queries, search and indexing
        • Internationalization (i18n)
        • Users and members
        • Security
        • Sessions and cookies
        • Images
        • Syndication
        • Miscellaneous information
          • Helper views and tools
          • Zope DateTime
          • Sending email
          • Annotations
          • Normalizing ids
          • Monkey-patching
          • Command-line interaction and scripting
          • Zope debug prompt
          • Clock and asyncronous tasks
          • Flowplayer
          • Navigation trees
            • Introduction
            • Creating a custom navigation tree
            • Excluding items in the navigation tree
            • Querying items in natural sort order
          • Creating your own Paster templates
          • Facebook integration
          • Slidehows and carousels
          • Upgrade tips
          • HTML manipulation and transformations
          • SQL
          • Changing Portal Transforms Settings via Python
          • Running plone.org site locally
          • Looking ahead towards Plone 5
          • Things We Don’t Like About Having to Rely Only on Browser Views
    • Developing for Plone Core
    • Dev helper packages
    • Importing content from other systems
    • Tutorials
  • Appendices
  • About this documentation
  • License for Plone Documentation
  • Asking for help
Table Of Content

Navigation trees¶

  • Introduction
  • Creating a custom navigation tree
  • Excluding items in the navigation tree
  • Querying items in natural sort order

Description

How navigation trees are generate in Plone and how to generate custom navigation trees.

Introduction¶

Plone exposes methods to build navigation trees.

  • Products.CMFPlone.browser.navtree
  • plone.app.layout.navigation.navtree.buildFolderTree

These are internally used by navigation portlet and sitemap.

Creating a custom navigation tree¶

See Products.PloneHelpCenter for full code.

The following example builds Table of Contents for Reference Manual content type:

class Strategy(NavtreeStrategyBase):

    rootPath = '/'.join(root.getPhysicalPath())
    showAllParents = False

strategy = Strategy()
query=  {'path'        : '/'.join(root.getPhysicalPath()),
         'object_provides' : 'Products.PloneHelpCenter.interfaces.IHelpCenterMultiPage',
         'sort_on'     : 'getObjPositionInParent'}

toc = buildFolderTree(self, current, query, strategy)['children']

Excluding items in the navigation tree¶

Your navigation tree strategy must define method nodeFilter() which can check for portal_catalog metadata column exclude_from_nav.

Example (from Products.CMFPlone.broser.navtree):

class SitemapNavtreeStrategy(NavtreeStrategyBase):

        def nodeFilter(self, node):
            item = node['item']
            if getattr(item, 'exclude_from_nav', False):
                return False
            else:
                return True

Querying items in natural sort order¶

Sometimes you want to display content items as they appear in Plone navigation. Below is an example which builds a flat vobulary for a form checbox list based on a custom portal_catalog query and root folder.

query_items_in_natural_sort_order:

from plone.app.layout.navigation.navtree import buildFolderTree
from plone.app.layout.navigation.navtree import NavtreeStrategyBase
# https://github.com/plone/Products.CMFPlone/blob/master/Products/CMFPlone/browser/navtree.py
from Products.CMFPlone.browser.navtree import SitemapNavtreeStrategy, DefaultNavtreeStrategy

def query_items_in_natural_sort_order(root, query):
    """
    Create a flattened out list of portal_catalog queried items in their natural depth first navigation order.

    @param root: Content item which acts as a navigation root

    @param query: Dictionary of portal_catalog query parameters

    @return: List of catalog brains
    """

    # Navigation tree base portal_catalog query parameters
    applied_query=  {
        'path' : '/'.join(root.getPhysicalPath()),
        'sort_on' : 'getObjPositionInParent'
    }

    # Apply caller's filters
    applied_query.update(query)

    # Set the navigation tree build strategy
    # - use navigation portlet strategy as base
    strategy = DefaultNavtreeStrategy(root)
    strategy.rootPath = '/'.join(root.getPhysicalPath())
    strategy.showAllParents = False
    strategy.bottomLevel = 999
    # This will yield out tree of nested dicts of
    # item brains with retrofitted navigational data
    tree = buildFolderTree(root, root, query, strategy=strategy)

    items = []

    def flatten(children):
        """ Recursively flatten the tree """
        for c in children:
            # Copy catalog brain object into the result
            items.append(c["item"])
            children = c.get("children", None)
            if children:
                flatten(children)

    flatten(tree["children"])

    return items

How to use:

def make_terms(items):
    """ Create zope.schema terms for vocab from tuples """
    terms = [ SimpleTerm(value=pair[0], token=pair[0], title=pair[1]) for pair in items ]
    return terms

@grok.provider(IContextSourceBinder)
def course_source(context):
    """
    Populate vocabulary with values from portal_catalog.

    @param context: z3c.form.Form context object (in our case site root)

    @return: SimpleVocabulary containg all areas as terms.
    """

    # Get site root from any content item using portal_url tool thru acquisition
    root = context.portal_url.getPortalObject()

    context = root.unrestrictedTraverse("courses")

    # We need to include "Folder" in the query even if it's not any of the results -
    # this is because the query criteria must match the root content item too
    brains = query_items_in_natural_sort_order(context, query = { "portal_type" : ["xxx2011.app.courseinfo", "xxx2011.app.subjectgroup", "xxx2011.app.coursecategory", "Folder"] })

    def filter(brain):
        # Remove some unwanted items from the list
        # XXX: Not needed anymore after new content types - remove
        x = brain["Title"]

        if "Carousel" in x:
            return False

        return True

    # Create a list of tuples (UID, Title) of results
    result = [ (brain["UID"], brain["Title"]) for brain in brains if filter(brain) == True ]

    # Convert tuples to SimpleTerm objects
    terms = make_terms(result)

    return SimpleVocabulary(terms)
  • Documentation
  • Developing for Plone
  • Programming Plone
  • Miscellaneous information
  • Navigation trees
  • Previous
  • Next
Further help resources:
  • Community discussion
  • Stackoverflow
  • IRC Chat
More info on the Plone project:
  • Plone Foundation
  • Providers & Consultants
About this documentation:
  • Contribute
  • These docs on Github
Download:
  • Plone
  • Plone add-ons
Plone

The text and illustrations in this website are licensed by the Plone Foundation under a Creative Commons Attribution 4.0 International license. Plone and the Plone® logo are registered trademarks of the Plone Foundation, registered in the United States and other countries. For guidelines on the permitted uses of the Plone trademarks, see https://plone.org/foundation/logo All other trademarks are owned by their respective owners. Hosted by Rackspace.

This page uses Google Analytics to collect statistics. You can disable it by blocking the JavaScript coming from www.google-analytics.com.