.. index:: z3c.menu, menu, viewlets
Navigation Menus with z3c.menu and Viewlets
*******************************************
At this point, it is pretty difficult to navigate between pages in our
application. It would be really nice to have a set of links that
appear on each page for navigating between the front page and the
contact add form. We can't just put hard links into the layout
template because we don't know what url the server will be running
under, and the relative paths change depending on which page you are
looking at. Thus we need something like z3c.menu.
z3c.menu is a very minimal package providing just a few helper classes
for making menus. The real power comes from a zope core package,
zope.viewlet. Here is the idea. Instead of working with the old zope
menus, which are rather inflexible, we want to use viewlets to more
easily define how and when menu items are displayed. Our navigation
menu will be a viewlet manager, and each link in the menu will
be a viewlet. In case you have not worked with viewlets before, I'll
try to explain what they are all about.
Setting up a Viewlet Manager
============================
What is a viewlet manager? In one sense, a viewlet manager is meant
to represent a certain region of a web page where you want to contain
any number of dynamicly generated pieces of content. One easy example
is the region on most blogs that contains a picture of the blogger, a
short description of the blog, a list of recent posts, a small
calendar and maybe a set of tags. In Zope terms, we would consider
each one of these pieces of content as a viewlet (think miniature
view), which are all collected together in a viewlet manager.
Getting to the point, let's create a viewlet manager. Start by
opening up ``src/zcontact/skin.py`` and adding the following code:
.. code-block:: python
from zope.viewlet.interfaces import IViewletManager
from zope.viewlet.manager import WeightOrderedViewletManager
class INavigationMenu(IViewletManager):
"""Navigation Menu Viewlet Manager."""
class NavigationMenu(WeightOrderedViewletManager):
zope.interface.implements(INavigationMenu)
When you create viewlets, they are registered to a particular viewlet
manager according to an interface. Thus we start by creating our own
interface called ``INavigationMenu`` just for the navigation menu,
which inherits from ``IViewletManager`` (lines 4-5). Next we create
an implementation of the ``INavigationMenu`` interface (lines 7-8).
The ``WeightOrderedViewletManager`` class can sort viewlets according
to a given weight, which could come in handy for a navigation menu.
Next we want to register our ViewletManager instance in zcml, so that
it can be rendered from a page template. Open up
``src/zcontact/skin.zcml`` and add the following registration:
.. code-block:: xml