Last modified: May 05, 2025 By Alexander Williams
Plone Traversal System Guide
Plone's traversal system maps URLs to content and views. It's a core feature that makes Plone flexible. This guide explains how to customize it.
Table Of Contents
Understanding Plone Traversal
Traversal is how Plone finds content by URL. When you request /folder/document
, Plone traverses from root to folder to document.
The system uses adapters and views to handle requests. You can hook into this process to create custom paths.
For more on Plone's architecture, see our Plone Fundamentals guide.
Basic View Registration
First, let's register a simple browser view. Views are Python classes that render content.
# In configure.zcml
<browser:page
name="my-view"
for="*"
class=".views.MyView"
template="mytemplate.pt"
permission="zope2.View"
/>
This registers a view available at context/@@my-view
. The for="*"
means it works on any content type.
Custom Traversal with Python
For more control, implement IPublishTraverse
. This lets you handle path segments directly.
from zope.interface import implementer
from zope.publisher.interfaces import IPublishTraverse
@implementer(IPublishTraverse)
class MyTraverser:
def __init__(self, context, request):
self.context = context
self.request = request
def publishTraverse(self, request, name):
# Handle custom path segments here
if name == 'special':
return SpecialContent()
return self.context
Register this in ZCML with an adapter. Now /context/special
will use your code.
Creating RESTful Endpoints
Traversal is perfect for REST APIs. Here's a simple JSON endpoint:
from plone.restapi.services import Service
from zope.interface import implementer
from zope.publisher.interfaces import IPublishTraverse
@implementer(IPublishTraverse)
class MyAPI(Service):
def __init__(self, context, request):
super().__init__(context, request)
self.params = []
def publishTraverse(self, request, name):
self.params.append(name)
return self
def reply(self):
return {
"context": self.context.title,
"params": self.params
}
Access this at /context/@myapi/path/parts
. It will return JSON with the path parts.
View Methods as Path Segments
You can expose view methods as path segments. This creates clean URLs.
class ReportView(BrowserView):
def __call__(self):
if len(self.request.traversed_subpath) > 0:
return getattr(self, self.request.traversed_subpath[0])()
return self.index()
def summary(self):
return "Summary report"
def details(self):
return "Detailed report"
Now /context/@@report/summary
shows the summary. /context/@@report/details
shows details.
Advanced: Custom Content Providers
For reusable components, use content providers. They work well with traversal.
First, register a provider in ZCML:
<browser:provider
name="my.provider"
for="*"
class=".providers.MyProvider"
permission="zope2.View"
/>
Then call it in templates with context/@@my.provider
. Learn more in our View Components Guide.
Security Considerations
Always check permissions in custom traversers. Use checkPermission()
from zope.security
.
For complex permission needs, see our Permissions Guide.
Debugging Traversal Issues
Common problems include:
- Missing ZCML registrations
- Incorrect interface implementations
- Permission errors
Use Plone's debug mode to test traversal. Add ?debug=true
to URLs.
Conclusion
Plone's traversal system is powerful. You can create custom URLs, REST APIs, and dynamic views.
Start simple with basic views. Then explore IPublishTraverse
for advanced routing.
Remember to always consider security. Test your custom paths thoroughly.
For more on Plone development, check our Add-on Guide.