Display forms
In the previous section, we created a view extending grok.View. This kind of view is the most common, but sometimes we want to make use of the widgets and information in the type's schema more directly, for example to invoke transforms or re-use more complex HTML.
To do this, you can use a display form. This is really just a view base class that knows about the schema of a type. We will use an example in session.py, with a template insession_templates/view.pt.
Note: Display forms involve the same type of overhead as add- and edit-forms. If you have complex forms with many behaviors, fieldsets and widget hints, you may notice a slow-down compared to standard views, at least on high volume sites.
The new view class is pretty much the same as before, except that we derive from dexterity.DisplayForm (plone.directives.dexterity.DisplayForm):
class View(dexterity.DisplayForm):
grok.context(ISession)
grok.require('zope2.View')
This gives our view a few extra properties that we can use in the template:
- view.w is a dictionary of all the display widgets, keyed by field names. For fields provided by behaviors, that is usually prefixed with the behavior interface name (IBehaviorInterface.field_name). For the default schema, unqualified names apply.
- view.widgets contains a list of widgets in schema order for the default fieldset
- view.groups contains a list of fieldsets in fieldset order.
- view.fieldsets contains a dict mapping fieldset name to fieldset
- On a fieldset (group), you can access a widgets list to get widgets in that fieldset
The w dict is the mostly commonly used.
The session_templates/view.pt template contains the following:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
lang="en"
metal:use-macro="context/main_template/macros/master"
i18n:domain="example.conference">
<body>
<metal:main fill-slot="main">
<tal:main-macro metal:define-macro="main">
<div tal:replace="structure provider:plone.abovecontenttitle" />
<h1 class="documentFirstHeading" tal:content="context/title" />
<div tal:replace="structure provider:plone.belowcontenttitle" />
<p class="documentDescription" tal:content="context/description" />
<div tal:replace="structure provider:plone.abovecontentbody" />
<div tal:content="structure view/w/details/render" />
<div tal:replace="structure provider:plone.belowcontentbody" />
</tal:main-macro>
</metal:main>
</body>
</html>
Notice how we use expressions like view/w/details/render (where details is the field name) to get the rendering of a widget. Other properties include __name__, the field name, and label, the field title.
