Widget-aware views ================== This package provides a view mixin class that can be used like a display form. The view is set up with widgets based on schema interfaces and/or form fields, and are available in 'display' mode. First, let's load this package's ZCML so that we can run the tests: >>> configuration = """\ ... ... ... ... ... ... ... """ >>> from StringIO import StringIO >>> from zope.configuration import xmlconfig >>> xmlconfig.xmlconfig(StringIO(configuration)) As with auto-forms, the widgets come from a primary schema interface, and optionally one or more secondary interfaces. Let's define two. >>> from zope.interface import Interface >>> from zope import schema >>> class IDefaultSchema(Interface): ... title = schema.TextLine(title=u"Title") ... body = schema.Text(title=u"Body") >>> class ISecondarySchema(Interface): ... summary = schema.Text(title=u"Summary") Let us also annotate these with some field hints, putting 'summary' into a secondary schema. >>> from plone.supermodel.interfaces import FIELDSETS_KEY >>> from plone.supermodel.model import Fieldset >>> ISecondarySchema.setTaggedValue(FIELDSETS_KEY, [Fieldset('secondary', fields=['summary'])]) A display form normally operates on a given context, although you could set ``ignoreContext = True`` and/or implement ``getContent()`` if applicable. The schema interfaces need to be provided by or adaptable from the context. For the purposes of this test, we'll just make them directly provided. >>> from zope.interface import implements >>> class Context(object): ... implements(IDefaultSchema, ISecondarySchema) ... title = u"" ... body = u"" ... summary = u"" We can now define a display form view. This should sub class or mix in WidgetsView. It must define either an ``index`` callable (usually a page template set by the ```` directive) or override the ``render`` method. It should also set the ``schema`` and ``additionalSchemata`` properties as required, using class variables, instance variables or properties. >>> from plone.autoform.view import WidgetsView >>> class TestView(WidgetsView): ... schema = IDefaultSchema ... additionalSchemata = (ISecondarySchema,) ... def render(self): ... return u"
My title widget says %s
" % self.w['title'].render() We need a test context and request, marked with the ``IFormLayer`` interface to make z3c.form happy: >>> from zope.publisher.browser import TestRequest >>> from z3c.form import interfaces >>> context = Context() >>> request = TestRequest(environ={'AUTHENTICATED_USER': 'user1'}, skin=interfaces.IFormLayer) Let us try to render this, to demonstrate that the widgets will be properly set up. >>> context.title = u"Test title" >>> context.body = u"Body" >>> context.summary = u"Summary" >>> view = TestView(context, request) >>> print view()
My title widget says Test title
More generally, the view supports the contract of display forms. After being updated, we have access to widgets in the default fieldset: >>> view.widgets.items() [('title', ), ('body', )] There is also a shortcut to allow access to any widget by (possibly prefixed) name: >>> view.w.items() [('body', ), ('ISecondarySchema.summary', ), ('title', )] You can also see fieldsets (groups) either in order: >>> view.groups (,) or looked up by name: >>> view.fieldsets.items() [('secondary', )] Note how the schema name is used as a prefix to all additional schemata. If you wish to flatten the namespace, you can set ignorePrefix to true: >>> view = TestView(context, request) >>> view.ignorePrefix = True >>> view.update() >>> view.w.items() [('body', ), ('summary', ), ('title', )] For supporting widget traversal it is necessary that after updating the form the widgets are present: >>> view2 = TestView(context, request) >>> view2.update() >>> view2.widgets >>> view2.widgets.keys() ['title', 'body']