documentation Plone5
stable
  • Introduction
  • Quickstart
  • Working with Content
  • Adapting & Extending Plone
  • Installing, Managing and Updating Plone
  • Developing for Plone
    • Developing add-ons for Plone
    • Programming with 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
        • Introduction
        • Cautions
        • Starting the debug prompt interactively
        • Code Snippets
        • Clock and asyncronous tasks
        • Flowplayer
        • Navigation trees
        • Slidehows and carousels
        • Upgrade tips
        • HTML manipulation and transformations
        • SQL
        • Changing Portal Transforms Settings via Python
        • Looking ahead towards Plone 5
    • Debugging
    • Writing tests
    • Plone style guides
    • Importing content from other sources
    • Tutorials
    • Selected Plone core package documentation
  • Appendices
  • About this documentation
  • License for Plone Documentation
  • Asking for help
documentation Plone5
  • Docs »
  • Developing for Plone »
  • Programming with Plone »
  • Miscellaneous information »
  • Navigation trees
  • Edit on GitHub

Navigation trees¶

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

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)

directlyProvides(course_source, IContextSourceBinder)
Next Previous

© Copyright 2016. Revision 689fc1f1.

Built with Sphinx using a theme provided by Read the Docs.