Use the same view in multiple models ************************************ :Author: Peter Bengtsson If you have multiple models each with their own views, perhaps you want all views to have access to one view in common. Purpose ======= You want all views in all models of an application to have access to a view without having to redefine this view in each model. For example you have a master template that defines the viewlet managers or ``METAL`` macros and you want all "sub views" to be able to use this. Prerequisities ============== Suppose you have a simple Grok application up and running and you've defined another model other than the application one called ``Term`` in a file called ``term.py`` like this: .. code-block:: python ## app.py class App(grok.Application, grok.Container): pass class Index(grok.View): # see app_templates/index.pt pass class Master(grok.View): # see app_templates/master.pt pass -------%<----------------------------- ## term.py class Term(grok.Model): pass class Index(grok.View): # see term_templates/index.pt pass Now, the ``App`` model has two views: ``index`` and ``master``. The ``Term`` model has only one view: ``index``. In both files called ``index.pt`` it says something like this on the very first line:: That works fine for ``app_templates/index.pt`` but will give you a ``TraversalError`` if you try to do the same in ``term_template/index.pt``. Step by step ============ The solution is really simple. Basically, change the ``Master`` view to this: .. code-block:: python from zope.interface import Interface class Master(grok.View): grok.context(Interface) With this you'll be able to reach ``context/@@master`` in any of the templates of your application which achieves the goal. Think of ``grok.context(...)`` as a filter mechanism that attaches itself into the "namespace tree" of your application at a certain "branch". By saying the context is ``Interface`` you're almost attaching the view to the trunk of the trunk. Further information =================== An alternative solution would be to use a base class and attach the ``Master`` view to that. Then you let all other models also subclass this base class and they get the shared functionality too. That approach has the advantage that it's more "standard pythonic" but you're then not using the powerful patterns that Grok offers plus you have to remember to add the base class on all other models which adds noise to the code.