Use the same view in multiple models
This How-to applies to:
Any version.
This How-to is intended for:
Developer
| Author: | Peter Bengtsson |
|---|
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:
## 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:
<html metal:use-macro="context/@@master/macros/page">
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:
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.

