[Checkins] SVN: z3c.form/trunk/src/z3c/form/group. Fixed a bug that prohibited groups from having different contents than the parent form. Previously, the groups contents were not being properly updated.

Paul Carduner paulcarduner at gmail.com
Tue Apr 8 16:17:20 EDT 2008


Log message for revision 85164:
  Fixed a bug that prohibited groups from having different contents than the parent form.  Previously, the groups contents were not being properly updated.
  
  This is also a great new way to avoid having to make custom widgets for object schema fields.  <german_accent>Cool</german_accent>
  

Changed:
  U   z3c.form/trunk/src/z3c/form/group.py
  U   z3c.form/trunk/src/z3c/form/group.txt

-=-
Modified: z3c.form/trunk/src/z3c/form/group.py
===================================================================
--- z3c.form/trunk/src/z3c/form/group.py	2008-04-08 19:39:04 UTC (rev 85163)
+++ z3c.form/trunk/src/z3c/form/group.py	2008-04-08 20:17:20 UTC (rev 85164)
@@ -63,7 +63,8 @@
         content = self.getContent()
         form.applyChanges(self, content, data)
         for group in self.groups:
-            groupChanged = form.applyChanges(group, content, data)
+            groupContent = group.getContent()
+            groupChanged = form.applyChanges(group, groupContent, data)
             changed = changed or groupChanged
         if changed:
             zope.event.notify(

Modified: z3c.form/trunk/src/z3c/form/group.txt
===================================================================
--- z3c.form/trunk/src/z3c/form/group.txt	2008-04-08 19:39:04 UTC (rev 85163)
+++ z3c.form/trunk/src/z3c/form/group.txt	2008-04-08 20:17:20 UTC (rev 85164)
@@ -440,3 +440,195 @@
   2006
 
 And that's it!
+
+
+Groups with Different Content
+-----------------------------
+
+You can customize the content for a group by overriding a group's
+``getContent`` method.  This is a very easy way to get around not
+having object widgets.  For example, suppose we want to maintain the
+vehicle owner's information in a separate class than the vehicle.  We
+might have an ``IVehicleOwner`` interface like so.
+
+  >>> class IVehicleOwner(zope.interface.Interface):
+  ...     firstName = zope.schema.TextLine(title=u'First Name')
+  ...     lastName = zope.schema.TextLine(title=u'Last Name')
+
+Then out ``IVehicleRegistration`` interface would include an object
+field for the owner instead of the ``firstName`` and ``lastName``
+fields.
+
+  >>> class IVehicleRegistration(zope.interface.Interface):
+  ...     owner = zope.schema.Object(title=u'Owner', schema=IVehicleOwner)
+  ...
+  ...     license = zope.schema.TextLine(title=u'License')
+  ...     address = zope.schema.TextLine(title=u'Address')
+  ...
+  ...     model = zope.schema.TextLine(title=u'Model')
+  ...     make = zope.schema.TextLine(title=u'Make')
+  ...     year = zope.schema.Int(title=u'Year')
+
+Now let's create simple implementations of these two interfaces.
+
+  >>> class VehicleOwner(object):
+  ...     zope.interface.implements(IVehicleOwner)
+  ...
+  ...     def __init__(self, **kw):
+  ...         for name, value in kw.items():
+  ...             setattr(self, name, value)
+
+  >>> class VehicleRegistration(object):
+  ...     zope.interface.implements(IVehicleRegistration)
+  ...
+  ...     def __init__(self, **kw):
+  ...         for name, value in kw.items():
+  ...             setattr(self, name, value)
+
+Now we can create a group just for the owner with its own
+``getContent`` method that simply returns the ``owner`` object field
+of the ``VehicleRegistration`` instance.
+
+  >>> class OwnerGroup(group.Group):
+  ...     label = u'Owner'
+  ...     fields = field.Fields(IVehicleOwner, prefix='owner')
+  ...
+  ...     def getContent(self):
+  ...         return self.context.owner
+
+When we create an Edit form for example, we should omit the ``owner``
+field which is taken care of with the group.
+
+  >>> class RegistrationEditForm(group.GroupForm, form.EditForm):
+  ...     fields = field.Fields(IVehicleRegistration).omit(
+  ...         'owner')
+  ...     groups = (OwnerGroup,)
+  ...
+  ...     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()
+
+When we render the form, the group appears as we would expect but with
+the ``owner`` prefix for the fields.
+
+  >>> print edit.render()
+  <html>
+    <body>
+      <form action=".">
+        <div class="row">
+          <label for="form-widgets-license">License</label>
+          <input type="text" id="form-widgets-license"
+                 name="form.widgets.license"
+                 class="text-widget required textline-field"
+                 value="MA 40387" />
+        </div>
+        <div class="row">
+          <label for="form-widgets-address">Address</label>
+          <input type="text" id="form-widgets-address"
+                 name="form.widgets.address"
+                 class="text-widget required textline-field"
+                 value="10 Main St, Maynard, MA" />
+        </div>
+        <div class="row">
+          <label for="form-widgets-model">Model</label>
+          <input type="text" id="form-widgets-model"
+                 name="form.widgets.model"
+                 class="text-widget required textline-field"
+                 value="BMW" />
+        </div>
+        <div class="row">
+          <label for="form-widgets-make">Make</label>
+          <input type="text" id="form-widgets-make"
+                 name="form.widgets.make"
+                 class="text-widget required textline-field"
+                 value="325" />
+        </div>
+        <div class="row">
+          <label for="form-widgets-year">Year</label>
+          <input type="text" id="form-widgets-year"
+                 name="form.widgets.year"
+                 class="text-widget required int-field" value="2005" />
+        </div>
+        <fieldgroup>
+          <legend>Owner</legend>
+          <div class="row">
+            <label for="form-widgets-owner-firstName">First Name</label>
+            <input type="text" id="form-widgets-owner-firstName"
+                   name="form.widgets.owner.firstName"
+                   class="text-widget required textline-field"
+                   value="Stephan" />
+          </div>
+          <div class="row">
+            <label for="form-widgets-owner-lastName">Last Name</label>
+            <input type="text" id="form-widgets-owner-lastName"
+                   name="form.widgets.owner.lastName"
+                   class="text-widget required textline-field"
+                   value="Richter" />
+          </div>
+        </fieldgroup>
+        <div class="action">
+          <input type="submit" id="form-buttons-apply"
+                 name="form.buttons.apply"
+                 class="submit-widget button-field" value="Apply" />
+        </div>
+      </form>
+    </body>
+  </html>
+
+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 edit.render()
+  <html>
+    <body>
+      <i>Data successfully updated.</i>
+      ...
+    </body>
+  </html>
+
+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
+  2005
+
+And that's it!



More information about the Checkins mailing list