[Checkins] SVN: z3c.form/branches/fieldsandcontentproviders/ rename interface (typo)
Godefroid Chapelle
gotcha at bubblenet.be
Thu Jul 1 06:47:16 EDT 2010
Log message for revision 114045:
rename interface (typo)
update and fix doctests
Changed:
U z3c.form/branches/fieldsandcontentproviders/CHANGES.txt
U z3c.form/branches/fieldsandcontentproviders/src/z3c/form/README.txt
U z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.py
U z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.txt
U z3c.form/branches/fieldsandcontentproviders/src/z3c/form/interfaces.py
-=-
Modified: z3c.form/branches/fieldsandcontentproviders/CHANGES.txt
===================================================================
--- z3c.form/branches/fieldsandcontentproviders/CHANGES.txt 2010-07-01 10:46:21 UTC (rev 114044)
+++ z3c.form/branches/fieldsandcontentproviders/CHANGES.txt 2010-07-01 10:47:15 UTC (rev 114045)
@@ -5,6 +5,11 @@
2.3.5 (unreleased)
------------------
+- Feature : mix fields and content providers in forms. This allow to enrich
+ the form by interlacing html snippets produced by content providers.
+ Adding html outside the widgets avoids the systematic need of
+ subclassing or changing the full widget rendering.
+
- Bug: Radio widget was not treating value as a list in hidden mode.
Modified: z3c.form/branches/fieldsandcontentproviders/src/z3c/form/README.txt
===================================================================
--- z3c.form/branches/fieldsandcontentproviders/src/z3c/form/README.txt 2010-07-01 10:46:21 UTC (rev 114044)
+++ z3c.form/branches/fieldsandcontentproviders/src/z3c/form/README.txt 2010-07-01 10:47:15 UTC (rev 114045)
@@ -48,6 +48,11 @@
Explains in detail the design goals surrounding widgets and widget managers
and how they were realized with the implemented API.
+- ``contentprovider.txt`` [advanced users]
+
+ Explains how to mix content providers in forms to render more html around
+ widgets.
+
- ``action.txt`` [advanced users]
Explains in detail the design goals surrounding action managers and
Modified: z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.py
===================================================================
--- z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.py 2010-07-01 10:46:21 UTC (rev 114044)
+++ z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.py 2010-07-01 10:47:15 UTC (rev 114045)
@@ -24,7 +24,6 @@
if names is not None:
for position, name in enumerate(names):
self[name] = lookup_
- self[name].position = position
def __setitem__(self, key, value):
factory = ContentProviderFactory(factory=value, name=key)
@@ -49,7 +48,7 @@
class FieldWidgetsAndProviders(FieldWidgets):
zope.component.adapts(
- interfaces.IFieldsAndContentProviderForm, interfaces.IFormLayer, zope.interface.Interface)
+ interfaces.IFieldsAndContentProvidersForm, interfaces.IFormLayer, zope.interface.Interface)
zope.interface.implementsOnly(interfaces.IWidgets)
def update(self):
@@ -57,6 +56,9 @@
uniqueOrderedKeys = self._data_keys
for name in self.form.contentProviders:
factory = self.form.contentProviders[name]
+ if factory.position is None:
+ raise ValueError("Position of the following"
+ " content provider should be an integer: '%s'." % name)
contentProvider = factory(self)
shortName = name
contentProvider.update()
Modified: z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.txt
===================================================================
--- z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.txt 2010-07-01 10:46:21 UTC (rev 114044)
+++ z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.txt 2010-07-01 10:47:15 UTC (rev 114045)
@@ -1,17 +1,18 @@
-ContentProviders
-----------------
+=================
+Content Providers
+=================
We want to mix fields and content providers.
This allow to enrich the form by interlacing html snippets produced by content
providers.
-For instance, we might want to include the table of results in a search form.
+For instance, we might want to render the table of results in a search form.
-We might also need to insert html close to a widget as a handle used when
+We might also need to render HTML close to a widget as a handle used when
improving UI with Ajax.
-Adding html outside the widgets avoids the systematic need of
+Adding HTML outside the widgets avoids the systematic need of
subclassing or changing the full widget rendering.
Test setup
@@ -54,9 +55,19 @@
... required=True)
...
-We will insert a content provider between the fields.
-We define a test content provider that prints extra help text::
+A class that implements the schema::
+ >>> class Person(object):
+ ... id = 'james'
+ ... fullname = 'James Bond'
+
+The usual request instance::
+
+ >>> request = TestRequest()
+
+We want to insert a content provider inbetween fields.
+We define a test content provider that renders extra help text::
+
>>> from zope.contentprovider.provider import ContentProviderBase
>>> class ExtendedHelp(ContentProviderBase):
...
@@ -76,34 +87,40 @@
>>> from z3c.form import field, form
>>> from zope.interface import implements
-To insert content providers, the following steps are needed :
+To enable content providers, the form class must :
- 1. the form class must implement ``IFieldsAndContentProviderForm``
- 2. the class must have a ``contentProviders`` attribute that is an instance
- of the ``ContentProviders`` class.
+ 1. implement ``IFieldsAndContentProvidersForm``
+ 2. have a ``contentProviders`` attribute that is
+ an instance of the ``ContentProviders`` class.
::
+ >>> from z3c.form.interfaces import IFieldsAndContentProvidersForm
>>> from z3c.form.contentprovider import ContentProviders
- >>> from z3c.form.interfaces import IFieldsAndContentProviderForm
+Content provider assignment
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Content providers classes (factories) can be assigned directly to the
+``ContentProviders`` container::
+
>>> class PersonForm(form.Form):
- ... implements(IFieldsAndContentProviderForm)
+ ... implements(IFieldsAndContentProvidersForm)
... fields = field.Fields(IPerson)
... ignoreContext = True
... contentProviders = ContentProviders()
... contentProviders['longHelp'] = ExtendedHelp
... contentProviders['longHelp'].position = 1
- >>> request = TestRequest()
- >>> class Person(object):
- ... id = 'james'
- ... fullname = 'James Bond'
- >>> context = Person()
- >>> personForm = PersonForm(context, request)
+Let's instantiate content and form instances::
+ >>> person = Person()
+ >>> personForm = PersonForm(person, request)
+
+Once the widget manager has been updated, it holds the content provider::
+
>>> from z3c.form.contentprovider import FieldWidgetsAndProviders
- >>> manager = FieldWidgetsAndProviders(personForm, request, context)
+ >>> manager = FieldWidgetsAndProviders(personForm, request, person)
>>> manager.ignoreContext = True
>>> manager.update()
>>> widgets = manager._data
@@ -120,8 +137,13 @@
>>> manager.get('longHelp').render()
'<div class="ex-help">Help about person james</div>'
-We can also define content provider by adaptation::
+Content provider lookup
+~~~~~~~~~~~~~~~~~~~~~~~
+Forms can also refer by name to content providers.
+
+Let's register a content provider by name as usual::
+
>>> from zope.component import provideAdapter
>>> from zope.contentprovider.interfaces import IContentProvider
>>> from z3c.form.interfaces import IFormLayer
@@ -131,16 +153,22 @@
... zope.interface.Interface),
... provides=IContentProvider, name='longHelp')
- >>> class AdaptedPersonForm(form.Form):
- ... implements(IFieldsAndContentProviderForm)
+Let the form refer to it::
+
+ >>> class LookupPersonForm(form.Form):
+ ... implements(IFieldsAndContentProvidersForm)
... prefix = 'form.'
... fields = field.Fields(IPerson)
... ignoreContext = True
... contentProviders = ContentProviders(['longHelp'])
... contentProviders['longHelp'].position = 2
+ >>> lookupForm = LookupPersonForm(person, request)
+
+After update, the widget manager refers to the content provider::
+
>>> from z3c.form.contentprovider import FieldWidgetsAndProviders
- >>> manager = FieldWidgetsAndProviders(personForm, request, context)
+ >>> manager = FieldWidgetsAndProviders(lookupForm, request, person)
>>> manager.ignoreContext = True
>>> manager.update()
>>> widgets = manager._data
@@ -157,13 +185,81 @@
>>> manager.get('longHelp').render()
'<div class="ex-help">Help about person james</div>'
+Providers position
+~~~~~~~~~~~~~~~~~~
+
+Until here, we have defined position for content providers without explaining
+how it is used.
+
+A position needs to be defined for each provider. Let's forget to define a
+position::
+
+ >>> class UndefinedPositionForm(form.Form):
+ ... implements(IFieldsAndContentProvidersForm)
+ ... prefix = 'form.'
+ ... fields = field.Fields(IPerson)
+ ... ignoreContext = True
+ ... contentProviders = ContentProviders(['longHelp'])
+
+ >>> form = UndefinedPositionForm(person, request)
+ >>> manager = FieldWidgetsAndProviders(form, request, person)
+ >>> manager.ignoreContext = True
+
+When updating the widget manager, we get an exception::
+
+ >>> manager.update()
+ Traceback (most recent call last):
+ ...
+ ValueError: Position of the following content provider should be an integer: 'longHelp'.
+
+Let's check positioning of content providers::
+
+ >>> LookupPersonForm.contentProviders['longHelp'].position = 0
+ >>> manager = FieldWidgetsAndProviders(lookupForm, request, person)
+ >>> manager.ignoreContext = True
+ >>> manager.update()
+ >>> manager.values()
+ [<ExtendedHelp object at ...>, <TextWidget 'form.widgets.id'>, <TextWidget 'form.widgets.fullname'>]
+
+ >>> LookupPersonForm.contentProviders['longHelp'].position = 1
+ >>> manager = FieldWidgetsAndProviders(lookupForm, request, person)
+ >>> manager.ignoreContext = True
+ >>> manager.update()
+ >>> manager.values()
+ [<TextWidget 'form.widgets.id'>, <ExtendedHelp object at ...>, <TextWidget 'form.widgets.fullname'>]
+
+ >>> LookupPersonForm.contentProviders['longHelp'].position = 2
+ >>> manager = FieldWidgetsAndProviders(lookupForm, request, person)
+ >>> manager.ignoreContext = True
+ >>> manager.update()
+ >>> manager.values()
+ [<TextWidget 'form.widgets.id'>, <TextWidget 'form.widgets.fullname'>, <ExtendedHelp object at ...>]
+
+Using value larger than sequence length implies end of sequence::
+
+ >>> LookupPersonForm.contentProviders['longHelp'].position = 3
+ >>> manager = FieldWidgetsAndProviders(lookupForm, request, person)
+ >>> manager.ignoreContext = True
+ >>> manager.update()
+ >>> manager.values()
+ [<TextWidget 'form.widgets.id'>, <TextWidget 'form.widgets.fullname'>, <ExtendedHelp object at ...>]
+
+A negative value is interpreted same as ``insert`` method of Python lists::
+
+ >>> LookupPersonForm.contentProviders['longHelp'].position = -1
+ >>> manager = FieldWidgetsAndProviders(lookupForm, request, person)
+ >>> manager.ignoreContext = True
+ >>> manager.update()
+ >>> manager.values()
+ [<TextWidget 'form.widgets.id'>, <ExtendedHelp object at ...>, <TextWidget 'form.widgets.fullname'>]
+
Rendering the form
------------------
-Once the update is complete we can render the form. Since we have not
-specified a template yet, we have to do this now. We have prepared a small and
-very simple template as part of this example:
+Once the form has been updated, it can be rendered.
+Since we have not assigned a template yet, we have to do it now.
+We have a small template as part of this example::
>>> import os
>>> from z3c.form import ptcompat as viewpagetemplatefile
@@ -180,17 +276,14 @@
>>> from z3c.form.testing import setupFormDefaults
>>> setupFormDefaults()
-Let's update the form before rendering it.
+``FieldWidgetsAndProviders`` is registered as widget manager for
+``IFieldsAndContentProvidersForm``::
>>> personForm.update()
-
-Because ``personFrom`` implements ``IFieldsAndContentProviderForm``,
-computed widgets is a ``FieldWidgetsAndProviders`` instance.
-
>>> personForm.widgets
<z3c.form.contentprovider.FieldWidgetsAndProviders object at ...>
-Let's now render the page::
+Let's render the form::
>>> print personForm.render()
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
@@ -216,4 +309,3 @@
</form>
</body>
</html>
-
Modified: z3c.form/branches/fieldsandcontentproviders/src/z3c/form/interfaces.py
===================================================================
--- z3c.form/branches/fieldsandcontentproviders/src/z3c/form/interfaces.py 2010-07-01 10:46:21 UTC (rev 114044)
+++ z3c.form/branches/fieldsandcontentproviders/src/z3c/form/interfaces.py 2010-07-01 10:47:15 UTC (rev 114045)
@@ -1012,7 +1012,7 @@
'the form.'),
schema=IFields)
-class IFieldsAndContentProviderForm(IForm):
+class IFieldsAndContentProvidersForm(IForm):
"""A form that is based upon defined fields and content providers"""
contentProviders = zope.schema.Object(
More information about the checkins
mailing list