[Checkins] SVN: z3c.form/branches/adamg-objectwidget/src/z3c/form/ add one more discriminator for ISubformFactory

Adam Groszer agroszer at gmail.com
Thu Oct 30 05:07:39 EDT 2008


Log message for revision 92689:
  add one more discriminator for ISubformFactory
  described ObjectWidget caveats
  

Changed:
  U   z3c.form/branches/adamg-objectwidget/src/z3c/form/README.txt
  A   z3c.form/branches/adamg-objectwidget/src/z3c/form/object-caveat.txt
  U   z3c.form/branches/adamg-objectwidget/src/z3c/form/object.py

-=-
Modified: z3c.form/branches/adamg-objectwidget/src/z3c/form/README.txt
===================================================================
--- z3c.form/branches/adamg-objectwidget/src/z3c/form/README.txt	2008-10-29 23:10:20 UTC (rev 92688)
+++ z3c.form/branches/adamg-objectwidget/src/z3c/form/README.txt	2008-10-30 09:07:36 UTC (rev 92689)
@@ -86,7 +86,11 @@
   This module provides a base class for add forms that work with the
   ``IAdding`` interface.
 
+- ``object-caveat.txt`` [informative]
 
+  Explains the current problems of ObjectWidget.
+
+
 Browser Documentation
 ---------------------
 
@@ -101,4 +105,3 @@
 
   Each field name documentation file comprehensively explains the widget and
   how it is ensured to work properly.
-

Added: z3c.form/branches/adamg-objectwidget/src/z3c/form/object-caveat.txt
===================================================================
--- z3c.form/branches/adamg-objectwidget/src/z3c/form/object-caveat.txt	                        (rev 0)
+++ z3c.form/branches/adamg-objectwidget/src/z3c/form/object-caveat.txt	2008-10-30 09:07:36 UTC (rev 92689)
@@ -0,0 +1,70 @@
+===================
+ObjectWidget caveat
+===================
+
+ObjectWidget itself seems to be fine, but we discovered a fundamental problem
+in z3.form.
+
+The meat is that widget value
+* validation
+* extraction
+* applying values
+need to be separated and made recursive-aware.
+
+Currently
+---------
+* There is a loop that extracts and validates each widgets value.
+  Then it moves on to the next widget in the same loop.
+* The problem is that the ObjectWidget MUST keep it's values in the object itself,
+  not in any dict or helper structure.
+  That means in case of a validation failure later in the loop the ObjectWidget's
+  values are already applied and cannot be reverted.
+* Also on a single level of widgets this loop might be OK,
+  because the loop is just flat.
+
+We need
+-------
+* To do a loop to validate ALL widget values.
+* To do a loop to extract ALL values. (maybe apply too, let's think about it...)
+* Then in a different loop apply those extracted (and validated) values.
+* Problem is that the current API does not support separate methods for that.
+* One more point is to take into account that with the ObjectWidget forms and
+  widgets can be _recursive_, that means there can be a
+  form-widgets-subform-widgets-subform-widgets level of widgets.
+
+
+An example:
+
+> The situation is the following:
+> - schema is like this:
+> class IMySubObject(zope.interface.Interface):
+>     foofield = zope.schema.Int(
+>         title=u"My foo field",
+>         default=1111,
+>         max=9999)
+>     barfield = zope.schema.Int(
+>         title=u"My dear bar",
+>         default=2222,
+>         required=False)
+> class IMyObject(zope.interface.Interface):
+>     subobject = zope.schema.Object(title=u'my object',
+>                                    schema=IMySubObject)
+>     name = zope.schema.TextLine(title=u'name')
+>
+> - on object editing
+> - we need to keep the (**old**) (IMySubObject) object in place
+>   -- do not create a new one
+> - value setting is done in the editform handleApply
+>   - extractData, extract needs to extract recursively
+>   - return assignable values
+>   - it has no idea about subobjects
+> - let's say the IMySubObject data is validated OK, but there's an
+>   error in IMyObject (with name)
+> - now the problem is:
+>   - IMyObject.subobject extract gets called first
+>     it sets the values on the existing object (and fires
+>     ObjectModifiedEvent)
+>   - IMyObject.name detects the error
+>     it does not set the value
+>   BUT IMyObject.subobject sticks to the extracted value that should be
+>   discarded, because the whole form did not validate?!?!?!


Property changes on: z3c.form/branches/adamg-objectwidget/src/z3c/form/object-caveat.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author Id Revision
Name: svn:eol-style
   + native

Modified: z3c.form/branches/adamg-objectwidget/src/z3c/form/object.py
===================================================================
--- z3c.form/branches/adamg-objectwidget/src/z3c/form/object.py	2008-10-29 23:10:20 UTC (rev 92688)
+++ z3c.form/branches/adamg-objectwidget/src/z3c/form/object.py	2008-10-30 09:07:36 UTC (rev 92689)
@@ -190,10 +190,11 @@
 
     def _getForm(self, content):
         form = getattr(self, 'form', None)
+        schema = getattr(self.field, 'schema', None)
+
         self.subform = zope.component.getMultiAdapter(
-            (content, self.request,
-             self.context,
-             form, self, self.field),
+            (content, self.request, self.context,
+             form, self, self.field, schema),
             interfaces.ISubformFactory)()
 
     def updateWidgets(self, setErrors=True):
@@ -252,20 +253,25 @@
     """Most basic-default subform factory adapter"""
 
     zope.interface.implements(interfaces.ISubformFactory)
-    zope.component.adapts(zope.interface.Interface, interfaces.IFormLayer,
-                          zope.interface.Interface,
-                          zope.interface.Interface, interfaces.IObjectWidget,
-                          zope.interface.Interface)
+    zope.component.adapts(zope.interface.Interface, #widget value
+                          interfaces.IFormLayer,    #request
+                          zope.interface.Interface, #widget context
+                          zope.interface.Interface, #form
+                          interfaces.IObjectWidget, #widget
+                          zope.interface.Interface, #field
+                          zope.interface.Interface) #field.schema
 
     factory = ObjectSubForm
 
-    def __init__(self, context, request, widgetContext, form, widget, field):
+    def __init__(self, context, request, widgetContext, form,
+                 widget, field, schema):
         self.context = context
         self.request = request
         self.widgetContext = widgetContext
         self.form = form
         self.widget = widget
         self.field = field
+        self.schema = schema
 
     def __call__(self):
         #value is the extracted data from the form



More information about the Checkins mailing list