PloneDocumentation
  • Documentation
  • Developing for Plone
  • Programming Plone
  • Miscellaneous information
  • Navigation trees
  • Previous
  • Next
  • Introduction
  • Working with Content
  • Adapting & Extending Plone
  • Managing, Administration of 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
          • 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
          • Search engine optimization (seo)
          • 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.

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