[Checkins] SVN: z3c.form/branches/sagblmi-nestedgroup/ Add nested group support
Laurent Mignon
Laurent.Mignon at softwareag.com
Thu Feb 26 12:05:42 EST 2009
Log message for revision 97323:
Add nested group support
Changed:
U z3c.form/branches/sagblmi-nestedgroup/CHANGES.txt
U z3c.form/branches/sagblmi-nestedgroup/src/z3c/form/group.py
U z3c.form/branches/sagblmi-nestedgroup/src/z3c/form/group.txt
-=-
Modified: z3c.form/branches/sagblmi-nestedgroup/CHANGES.txt
===================================================================
--- z3c.form/branches/sagblmi-nestedgroup/CHANGES.txt 2009-02-26 17:05:29 UTC (rev 97322)
+++ z3c.form/branches/sagblmi-nestedgroup/CHANGES.txt 2009-02-26 17:05:41 UTC (rev 97323)
@@ -4,6 +4,7 @@
Version 2.0.0 (unreleased)
--------------------------
+- Feature: Added Nested group support.
- Feature: Added labelRequired and requiredInfo form attributes. This is
useful for conditional rendering a required info legend in form templates.
Modified: z3c.form/branches/sagblmi-nestedgroup/src/z3c/form/group.py
===================================================================
--- z3c.form/branches/sagblmi-nestedgroup/src/z3c/form/group.py 2009-02-26 17:05:29 UTC (rev 97322)
+++ z3c.form/branches/sagblmi-nestedgroup/src/z3c/form/group.py 2009-02-26 17:05:41 UTC (rev 97323)
@@ -21,9 +21,12 @@
from z3c.form import form, interfaces
from zope.interface import implements
+
class Group(form.BaseForm):
implements(interfaces.IGroup)
+ groups = ()
+
def __init__(self, context, request, parentForm):
self.context = context
self.request = request
@@ -39,8 +42,46 @@
setattr(self.widgets, attrName, value)
self.widgets.update()
+ def update(self):
+ '''See interfaces.IForm'''
+ self.updateWidgets()
+ groups = []
+ for groupClass in self.groups:
+ # only instantiate the groupClass if it hasn't already
+ # been instantiated
+ if interfaces.IGroup.providedBy(groupClass):
+ group = groupClass
+ else:
+ group = groupClass(self.context, self.request, self)
+ group.update()
+ groups.append(group)
+ self.groups = tuple(groups)
+
+ def extractData(self):
+ '''See interfaces.IForm'''
+ data, errors = super(Group, self).extractData()
+ for group in self.groups:
+ groupData, groupErrors = group.extractData()
+ data.update(groupData)
+ if groupErrors:
+ if errors:
+ errors += groupErrors
+ else:
+ errors = groupErrors
+ return data, errors
+ def applyChanges(self, data):
+ '''See interfaces.IEditForm'''
+ descriptions = []
+ content = self.getContent()
+ changed = form.applyChanges(self, content, data)
+ for group in self.groups:
+ groupChanged = group.applyChanges(data)
+ for interface, names in groupChanged.items():
+ changed[interface] = changed.get(interface, []) + names
+ return changed
+
class GroupForm(object):
"""A mix-in class for add and edit forms to support groups."""
@@ -65,8 +106,7 @@
content = self.getContent()
changed = form.applyChanges(self, content, data)
for group in self.groups:
- groupContent = group.getContent()
- groupChanged = form.applyChanges(group, groupContent, data)
+ groupChanged = group.applyChanges(data)
for interface, names in groupChanged.items():
changed[interface] = changed.get(interface, []) + names
if changed:
@@ -75,7 +115,8 @@
zope.lifecycleevent.Attributes(interface, *names))
# Send out a detailed object-modified event
zope.event.notify(
- zope.lifecycleevent.ObjectModifiedEvent(content, *descriptions))
+ zope.lifecycleevent.ObjectModifiedEvent(content,
+ *descriptions))
return changed
Modified: z3c.form/branches/sagblmi-nestedgroup/src/z3c/form/group.txt
===================================================================
--- z3c.form/branches/sagblmi-nestedgroup/src/z3c/form/group.txt 2009-02-26 17:05:29 UTC (rev 97322)
+++ z3c.form/branches/sagblmi-nestedgroup/src/z3c/form/group.txt 2009-02-26 17:05:41 UTC (rev 97323)
@@ -643,4 +643,111 @@
>>> reg.year
u'2005'
+
+Nested Groups
+-----------------
+
+The group can contains groups.
+Let's adapt the previous RegistrationEditForm
+
+ >>> class OwnerGroup(group.Group):
+ ... label = u'Owner'
+ ... fields = field.Fields(IVehicleOwner, prefix='owner')
+ ...
+ ... def getContent(self):
+ ... return self.context.owner
+
+ >>> class VehicleRegistrationGroup(group.Group):
+ ... label = u'Registration'
+ ... fields = field.Fields(IVehicleRegistration).omit(
+ ... 'owner')
+ ... groups = (OwnerGroup,)
+
+ >>> class RegistrationEditForm(group.GroupForm, form.EditForm):
+ ... groups = (VehicleRegistrationGroup,)
+ ...
+ ... template = viewpagetemplatefile.ViewPageTemplateFile(
+ ... 'simple_groupedit.pt', os.path.dirname(tests.__file__))
+
+
+ >>> reg = VehicleRegistration(
+ ... license=u'MA 40387',
+ ... address=u'10 Main St, Maynard, MA',
+ ... model=u'BMW',
+ ... make=u'325',
+ ... year=u'2005',
+ ... owner=VehicleOwner(firstName=u'Stephan',
+ ... lastName=u'Richter'))
+ >>> request = testing.TestRequest()
+
+ >>> edit = RegistrationEditForm(reg, request)
+ >>> edit.update()
+
+Now let's try and edit the owner. For example, suppose that Stephan
+Richter gave his BMW to Paul Carduner because he is such a nice guy.
+
+ >>> request = testing.TestRequest(form={
+ ... 'form.widgets.owner.firstName': u'Paul',
+ ... 'form.widgets.owner.lastName': u'Carduner',
+ ... 'form.widgets.license': u'MA 4038765',
+ ... 'form.widgets.address': u'Berkeley',
+ ... 'form.widgets.model': u'BMW',
+ ... 'form.widgets.make': u'325',
+ ... 'form.widgets.year': u'2005',
+ ... 'form.buttons.apply': u'Apply'
+ ... })
+ >>> edit = RegistrationEditForm(reg, request)
+ >>> edit.update()
+
+We'll see if everything worked on the form side.
+
+ >>> print testing.render(edit, './/xmlns:i')
+ <i>Data successfully updated.</i>
+
+Now the owner object should have updated fields.
+
+ >>> reg.owner.firstName
+ u'Paul'
+ >>> reg.owner.lastName
+ u'Carduner'
+ >>> reg.license
+ u'MA 4038765'
+ >>> reg.address
+ u'Berkeley'
+ >>> reg.model
+ u'BMW'
+ >>> reg.make
+ u'325'
+ >>> reg.year
+ u'2005'
+
+So what happens, if errors happen inside a nested group?
+
+ >>> request = testing.TestRequest(form={
+ ... 'form.widgets.owner.firstName': u'Paul',
+ ... 'form.widgets.license': u'MA 4038765',
+ ... 'form.widgets.model': u'BMW',
+ ... 'form.widgets.make': u'325',
+ ... 'form.widgets.year': u'2005',
+ ... 'form.buttons.apply': u'Apply'
+ ... })
+
+ >>> edit = RegistrationEditForm(reg, request)
+ >>> edit.update()
+ >>> data, errors = edit.extractData()
+ >>> " ".join(["%s %s"%(error.widget.label, error.render()) for error in errors])
+ u'Address \n <div class="error">Required input is missing.</div>\n\n Last Name \n <div class="error">Required input is missing.</div>\n\n'
+
+ >>> print testing.render(edit, './/xmlns:i')
+ <i >There were some errors.</i>
+
+ >>> print testing.render(edit, './/xmlns:fieldset[1]/xmlns:ul')
+ <ul >
+ <li>
+ Address:
+ <div class="error">Required input is missing.</div>
+ </li>
+ </ul>
+
+
And that's it!
More information about the Checkins
mailing list