[Checkins] SVN: z3c.form/branches/adamg-objectwidget/src/z3c/form/ bunch of XXX's smashed
Adam Groszer
agroszer at gmail.com
Thu Oct 9 04:42:24 EDT 2008
Log message for revision 91917:
bunch of XXX's smashed
most important: in-place object editing, prefix
Changed:
U z3c.form/branches/adamg-objectwidget/src/z3c/form/browser/object.py
U z3c.form/branches/adamg-objectwidget/src/z3c/form/browser/object.txt
U z3c.form/branches/adamg-objectwidget/src/z3c/form/form.py
U z3c.form/branches/adamg-objectwidget/src/z3c/form/interfaces.py
U z3c.form/branches/adamg-objectwidget/src/z3c/form/object.py
-=-
Modified: z3c.form/branches/adamg-objectwidget/src/z3c/form/browser/object.py
===================================================================
--- z3c.form/branches/adamg-objectwidget/src/z3c/form/browser/object.py 2008-10-09 06:37:13 UTC (rev 91916)
+++ z3c.form/branches/adamg-objectwidget/src/z3c/form/browser/object.py 2008-10-09 08:42:21 UTC (rev 91917)
@@ -20,20 +20,14 @@
def updateWidgets(self):
if self._value is not interfaces.NOVALUE:
self.subform = ObjectSubForm(self._value, self)
+ ignore = None
else:
self.subform = ObjectSubForm(None, self)
- self.subform.ignoreContext=True
+ ignore = True
- self.subform.update()
+ self.subform.update(ignore)
def update(self):
- try:
- self._value = getattr(self.context, self.field.__name__)
- except AttributeError:
- #lame, mostly for adding
- if self.context is not None:
- self._value = self.context
-
super(ObjectWidget, self).update()
self.updateWidgets()
Modified: z3c.form/branches/adamg-objectwidget/src/z3c/form/browser/object.txt
===================================================================
--- z3c.form/branches/adamg-objectwidget/src/z3c/form/browser/object.txt 2008-10-09 06:37:13 UTC (rev 91916)
+++ z3c.form/branches/adamg-objectwidget/src/z3c/form/browser/object.txt 2008-10-09 08:42:21 UTC (rev 91917)
@@ -111,7 +111,8 @@
</div>
<div class="widget">
<input class="text-widget required int-field"
- id="subobject-widgets-foofield" name="subobject.widgets.foofield"
+ id="subobject-widgets-foofield"
+ name="subobject.widgets.foofield"
type="text" value="1,111">
</div>
<div class="label">
@@ -120,8 +121,10 @@
</label>
</div>
<div class="widget">
- <input class="text-widget int-field" id="subobject-widgets-barfield"
- name="subobject.widgets.barfield" type="text" value="2,222">
+ <input class="text-widget int-field"
+ id="subobject-widgets-barfield"
+ name="subobject.widgets.barfield"
+ type="text" value="2,222">
</div>
<input name="subobject-empty-marker" type="hidden" value="1">
</div>
@@ -156,7 +159,8 @@
</div>
<div class="widget">
<input class="text-widget required int-field"
- id="subobject-widgets-foofield" name="subobject.widgets.foofield"
+ id="subobject-widgets-foofield"
+ name="subobject.widgets.foofield"
type="text" value="42">
</div>
<div class="label">
@@ -165,8 +169,10 @@
</label>
</div>
<div class="widget">
- <input class="text-widget int-field" id="subobject-widgets-barfield"
- name="subobject.widgets.barfield" type="text" value="666">
+ <input class="text-widget int-field"
+ id="subobject-widgets-barfield"
+ name="subobject.widgets.barfield"
+ type="text" value="666">
</div>
<input name="subobject-empty-marker" type="hidden" value="1">
</div>
@@ -190,7 +196,8 @@
</div>
<div class="widget">
<input class="text-widget required int-field"
- id="subobject-widgets-foofield" name="subobject.widgets.foofield"
+ id="subobject-widgets-foofield"
+ name="subobject.widgets.foofield"
type="text" value="2">
</div>
<div class="label">
@@ -199,8 +206,10 @@
</label>
</div>
<div class="widget">
- <input class="text-widget int-field" id="subobject-widgets-barfield"
- name="subobject.widgets.barfield" type="text" value="999">
+ <input class="text-widget int-field"
+ id="subobject-widgets-barfield"
+ name="subobject.widgets.barfield"
+ type="text" value="999">
</div>
<input name="subobject-empty-marker" type="hidden" value="1">
</div>
@@ -208,6 +217,7 @@
</html>
+
Error handling is next. Let's use the value "bad" (an invalid integer literal)
as input for our internal (sub) widget.
@@ -228,7 +238,8 @@
</div>
<div class="widget">
<input class="text-widget required int-field"
- id="subobject-widgets-foofield" name="subobject.widgets.foofield"
+ id="subobject-widgets-foofield"
+ name="subobject.widgets.foofield"
type="text" value="2">
</div>
<div class="label">
@@ -240,8 +251,10 @@
<div class="error">The entered value is not a valid integer literal.</div>
</div>
<div class="widget">
- <input class="text-widget int-field" id="subobject-widgets-barfield"
- name="subobject.widgets.barfield" type="text" value="bad">
+ <input class="text-widget int-field"
+ id="subobject-widgets-barfield"
+ name="subobject.widgets.barfield"
+ type="text" value="bad">
</div>
<input name="subobject-empty-marker" type="hidden" value="1">
</div>
@@ -287,6 +300,9 @@
>>> request = TestRequest()
>>> myaddform = MyAddForm(root, request)
+#>>> from pub.dbgpclient import brk; brk('192.168.32.1')
+
+
>>> myaddform.update()
As usual, the form contains a widget manager with the expected widget
@@ -327,24 +343,27 @@
<label for="form-widgets-subobject">my object</label>
<div class="object-widget required">
<div class="label">
- <label for="subobject-widgets-foofield">
+ <label for="form-widgets-subobject-widgets-foofield">
<span>My foo field</span>
<span class="required">*</span>
</label>
</div>
<div class="widget">
<input class="text-widget required int-field"
- id="subobject-widgets-foofield" name="subobject.widgets.foofield"
+ id="form-widgets-subobject-widgets-foofield"
+ name="form.widgets.subobject.widgets.foofield"
type="text" value="1,111">
</div>
<div class="label">
- <label for="subobject-widgets-barfield">
+ <label for="form-widgets-subobject-widgets-barfield">
<span>My dear bar</span>
</label>
</div>
<div class="widget">
- <input class="text-widget int-field" id="subobject-widgets-barfield"
- name="subobject.widgets.barfield" type="text" value="2,222">
+ <input class="text-widget int-field"
+ id="form-widgets-subobject-widgets-barfield"
+ name="form.widgets.subobject.widgets.barfield"
+ type="text" value="2,222">
</div>
<input name="form.widgets.subobject-empty-marker" type="hidden"
value="1">
@@ -372,11 +391,12 @@
Let's try to add an object:
- >>> request = TestRequest(form={'subobject.widgets.foofield':u'66',
- ... 'subobject.widgets.barfield':u'99',
- ... 'form.widgets.name':u'first',
- ... 'form.widgets.subobject-empty-marker':u'1',
- ... 'form.buttons.add':'Add'})
+ >>> request = TestRequest(form={
+ ... 'form.widgets.subobject.widgets.foofield':u'66',
+ ... 'form.widgets.subobject.widgets.barfield':u'99',
+ ... 'form.widgets.name':u'first',
+ ... 'form.widgets.subobject-empty-marker':u'1',
+ ... 'form.buttons.add':'Add'})
>>> myaddform.request = request
>>> myaddform.update()
MyAddForm.create {'subobject': <z3c.form.testing.MySubObject object at ...>,
@@ -416,24 +436,27 @@
<label for="form-widgets-subobject">my object</label>
<div class="object-widget required">
<div class="label">
- <label for="subobject-widgets-foofield">
+ <label for="form-widgets-subobject-widgets-foofield">
<span>My foo field</span>
<span class="required">*</span>
</label>
</div>
<div class="widget">
<input class="text-widget required int-field"
- id="subobject-widgets-foofield" name="subobject.widgets.foofield"
+ id="form-widgets-subobject-widgets-foofield"
+ name="form.widgets.subobject.widgets.foofield"
type="text" value="66">
</div>
<div class="label">
- <label for="subobject-widgets-barfield">
+ <label for="form-widgets-subobject-widgets-barfield">
<span>My dear bar</span>
</label>
</div>
<div class="widget">
- <input class="text-widget int-field" id="subobject-widgets-barfield"
- name="subobject.widgets.barfield" type="text" value="99">
+ <input class="text-widget int-field"
+ id="form-widgets-subobject-widgets-barfield"
+ name="form.widgets.subobject.widgets.barfield"
+ type="text" value="99">
</div>
<input name="form.widgets.subobject-empty-marker" type="hidden"
value="1">
@@ -454,11 +477,12 @@
Let's modify the values:
- >>> request = TestRequest(form={'subobject.widgets.foofield':u'43',
- ... 'subobject.widgets.barfield':u'55',
- ... 'form.widgets.name':u'first',
- ... 'form.widgets.subobject-empty-marker':u'1',
- ... 'form.buttons.apply':'Apply'})
+ >>> request = TestRequest(form={
+ ... 'form.widgets.subobject.widgets.foofield':u'43',
+ ... 'form.widgets.subobject.widgets.barfield':u'55',
+ ... 'form.widgets.name':u'first',
+ ... 'form.widgets.subobject-empty-marker':u'1',
+ ... 'form.buttons.apply':'Apply'})
They are still the same:
@@ -468,9 +492,12 @@
99
>>> editform.request = request
+
+#>>> from pub.dbgpclient import brk; brk('192.168.32.1')
+
>>> editform.update()
-Until we update the form:
+Until we have updated the form:
>>> root['first'].subobject.foofield
43
@@ -489,24 +516,27 @@
<label for="form-widgets-subobject">my object</label>
<div class="object-widget required">
<div class="label">
- <label for="subobject-widgets-foofield">
+ <label for="form-widgets-subobject-widgets-foofield">
<span>My foo field</span>
<span class="required">*</span>
</label>
</div>
<div class="widget">
<input class="text-widget required int-field"
- id="subobject-widgets-foofield" name="subobject.widgets.foofield"
+ id="form-widgets-subobject-widgets-foofield"
+ name="form.widgets.subobject.widgets.foofield"
type="text" value="43">
</div>
<div class="label">
- <label for="subobject-widgets-barfield">
+ <label for="form-widgets-subobject-widgets-barfield">
<span>My dear bar</span>
</label>
</div>
<div class="widget">
- <input class="text-widget int-field" id="subobject-widgets-barfield"
- name="subobject.widgets.barfield" type="text" value="55">
+ <input class="text-widget int-field"
+ id="form-widgets-subobject-widgets-barfield"
+ name="form.widgets.subobject.widgets.barfield"
+ type="text" value="55">
</div>
<input name="form.widgets.subobject-empty-marker" type="hidden"
value="1">
@@ -525,13 +555,49 @@
</body>
</html>
+
+Let's see if the widget keeps the old object on editing:
+
+We add a special property to keep track of the object:
+
+ >>> root['first'].__marker__ = "ThisMustStayTheSame"
+
+ >>> root['first'].subobject.foofield
+ 43
+ >>> root['first'].subobject.barfield
+ 55
+
+Let's modify the values:
+
+ >>> request = TestRequest(form={
+ ... 'form.widgets.subobject.widgets.foofield':u'666',
+ ... 'form.widgets.subobject.widgets.barfield':u'999',
+ ... 'form.widgets.name':u'first',
+ ... 'form.widgets.subobject-empty-marker':u'1',
+ ... 'form.buttons.apply':'Apply'})
+
+ >>> editform.request = request
+
+ >>> editform.update()
+
+Until we have updated the form:
+
+ >>> root['first'].subobject.foofield
+ 666
+ >>> root['first'].subobject.barfield
+ 999
+ >>> root['first'].__marker__
+ 'ThisMustStayTheSame'
+
+
Let's make a nasty error, by typing 'bad' instead of an integer:
- >>> request = TestRequest(form={'subobject.widgets.foofield':u'99',
- ... 'subobject.widgets.barfield':u'bad',
- ... 'form.widgets.name':u'first',
- ... 'form.widgets.subobject-empty-marker':u'1',
- ... 'form.buttons.apply':'Apply'})
+ >>> request = TestRequest(form={
+ ... 'form.widgets.subobject.widgets.foofield':u'99',
+ ... 'form.widgets.subobject.widgets.barfield':u'bad',
+ ... 'form.widgets.name':u'first',
+ ... 'form.widgets.subobject-empty-marker':u'1',
+ ... 'form.buttons.apply':'Apply'})
>>> editform.request = request
>>> editform.update()
@@ -557,18 +623,19 @@
<label for="form-widgets-subobject">my object</label>
<div class="object-widget required">
<div class="label">
- <label for="subobject-widgets-foofield">
+ <label for="form-widgets-subobject-widgets-foofield">
<span>My foo field</span>
<span class="required">*</span>
</label>
</div>
<div class="widget">
<input class="text-widget required int-field"
- id="subobject-widgets-foofield" name="subobject.widgets.foofield"
+ id="form-widgets-subobject-widgets-foofield"
+ name="form.widgets.subobject.widgets.foofield"
type="text" value="99">
</div>
<div class="label">
- <label for="subobject-widgets-barfield">
+ <label for="form-widgets-subobject-widgets-barfield">
<span>My dear bar</span>
</label>
</div>
@@ -576,8 +643,10 @@
<div class="error">The entered value is not a valid integer literal.</div>
</div>
<div class="widget">
- <input class="text-widget int-field" id="subobject-widgets-barfield"
- name="subobject.widgets.barfield" type="text" value="bad">
+ <input class="text-widget int-field"
+ id="form-widgets-subobject-widgets-barfield"
+ name="form.widgets.subobject.widgets.barfield"
+ type="text" value="bad">
</div>
<input name="form.widgets.subobject-empty-marker" type="hidden"
value="1">
@@ -599,18 +668,19 @@
The object values must stay at the old ones:
>>> root['first'].subobject.foofield
- 43
+ 666
>>> root['first'].subobject.barfield
- 55
+ 999
Let's make more errors:
Now we enter 'bad' and '999999', where '999999' hits the upper limit of the field.
- >>> request = TestRequest(form={'subobject.widgets.foofield':u'999999',
- ... 'subobject.widgets.barfield':u'bad',
- ... 'form.widgets.name':u'first',
- ... 'form.widgets.subobject-empty-marker':u'1',
- ... 'form.buttons.apply':'Apply'})
+ >>> request = TestRequest(form={
+ ... 'form.widgets.subobject.widgets.foofield':u'999999',
+ ... 'form.widgets.subobject.widgets.barfield':u'bad',
+ ... 'form.widgets.name':u'first',
+ ... 'form.widgets.subobject-empty-marker':u'1',
+ ... 'form.buttons.apply':'Apply'})
>>> editform.request = request
>>> editform.update()
@@ -637,7 +707,7 @@
<label for="form-widgets-subobject">my object</label>
<div class="object-widget required">
<div class="label">
- <label for="subobject-widgets-foofield">
+ <label for="form-widgets-subobject-widgets-foofield">
<span>My foo field</span>
<span class="required">*</span>
</label>
@@ -647,11 +717,12 @@
</div>
<div class="widget">
<input class="text-widget required int-field"
- id="subobject-widgets-foofield" name="subobject.widgets.foofield"
+ id="form-widgets-subobject-widgets-foofield"
+ name="form.widgets.subobject.widgets.foofield"
type="text" value="999999">
</div>
<div class="label">
- <label for="subobject-widgets-barfield">
+ <label for="form-widgets-subobject-widgets-barfield">
<span>My dear bar</span>
</label>
</div>
@@ -659,8 +730,10 @@
<div class="error">The entered value is not a valid integer literal.</div>
</div>
<div class="widget">
- <input class="text-widget int-field" id="subobject-widgets-barfield"
- name="subobject.widgets.barfield" type="text" value="bad">
+ <input class="text-widget int-field"
+ id="form-widgets-subobject-widgets-barfield"
+ name="form.widgets.subobject.widgets.barfield"
+ type="text" value="bad">
</div>
<input name="form.widgets.subobject-empty-marker" type="hidden"
value="1">
@@ -682,9 +755,9 @@
And of course, the object values do not get modified:
>>> root['first'].subobject.foofield
- 43
+ 666
>>> root['first'].subobject.barfield
- 55
+ 999
Simple but often used use-case is the display form:
@@ -701,23 +774,23 @@
<label for="form-widgets-subobject">my object</label>
<div class="object-widget required">
<div class="label">
- <label for="subobject-widgets-foofield">
+ <label for="form-widgets-subobject-widgets-foofield">
<span>My foo field</span>
<span class="required">*</span>
</label>
</div>
<div class="widget">
<span class="text-widget required int-field"
- id="subobject-widgets-foofield">43</span>
+ id="form-widgets-subobject-widgets-foofield">666</span>
</div>
<div class="label">
- <label for="subobject-widgets-barfield">
+ <label for="form-widgets-subobject-widgets-barfield">
<span>My dear bar</span>
</label>
</div>
<div class="widget">
<span class="text-widget int-field"
- id="subobject-widgets-barfield">55</span>
+ id="form-widgets-subobject-widgets-barfield">999</span>
</div>
</div>
</div>
Modified: z3c.form/branches/adamg-objectwidget/src/z3c/form/form.py
===================================================================
--- z3c.form/branches/adamg-objectwidget/src/z3c/form/form.py 2008-10-09 06:37:13 UTC (rev 91916)
+++ z3c.form/branches/adamg-objectwidget/src/z3c/form/form.py 2008-10-09 08:42:21 UTC (rev 91917)
@@ -41,7 +41,9 @@
(content, field.field), interfaces.IDataManager)
oldValue = dm.get()
# Only update the data, if it is different
- if dm.get() != data[name]:
+ # Or it is an Object, in case we'll never know
+ if (dm.get() != data[name]
+ or zope.schema.interfaces.IObject.providedBy(field.field)):
dm.set(data[name])
# Record the change using information required later
changes.setdefault(dm.field.interface, []).append(name)
Modified: z3c.form/branches/adamg-objectwidget/src/z3c/form/interfaces.py
===================================================================
--- z3c.form/branches/adamg-objectwidget/src/z3c/form/interfaces.py 2008-10-09 06:37:13 UTC (rev 91916)
+++ z3c.form/branches/adamg-objectwidget/src/z3c/form/interfaces.py 2008-10-09 08:42:21 UTC (rev 91917)
@@ -329,10 +329,11 @@
class IObjectFactory(zope.interface.Interface):
"""Factory that will instatiate our objects for ObjectWidget
- It could also pre-populate properties as it gets the value passed
+ It could also pre-populate properties as it gets the values extracted
+ from the form passed in ``value``
"""
- def get(value):
+ def __call__(value):
"""return a default object created to be populated
"""
Modified: z3c.form/branches/adamg-objectwidget/src/z3c/form/object.py
===================================================================
--- z3c.form/branches/adamg-objectwidget/src/z3c/form/object.py 2008-10-09 06:37:13 UTC (rev 91916)
+++ z3c.form/branches/adamg-objectwidget/src/z3c/form/object.py 2008-10-09 08:42:21 UTC (rev 91917)
@@ -23,7 +23,7 @@
from z3c.form.converter import BaseDataConverter
-from z3c.form import form, interfaces
+from z3c.form import form, interfaces, util
from z3c.form.field import Fields
from z3c.form.error import MultipleErrors
from z3c.form.i18n import MessageFactory as _
@@ -34,8 +34,8 @@
def __init__(self, context, parentWidget):
self.context = context
self.request = parentWidget.request
- self.parentWidget = parentWidget
- self.parentForm = self.__parent__ = parentWidget.form
+ self.__parent__ = parentWidget
+ self.parentForm = parentWidget.form
def _validate(self):
for widget in self.widgets.values():
@@ -47,7 +47,7 @@
zope.component.getMultiAdapter(
(self.context,
self.request,
- self.parentWidget.form,
+ self.parentForm,
getattr(widget, 'field', None),
widget),
interfaces.IValidator).validate(value)
@@ -55,27 +55,30 @@
# on exception, setup the widget error message
view = zope.component.getMultiAdapter(
(error, self.request, widget, widget.field,
- self.parentWidget.form, self.context),
+ self.parentForm, self.context),
interfaces.IErrorViewSnippet)
view.update()
widget.error = view
- def update(self):
- self.fields = Fields(self.parentWidget.field.schema)
+ def update(self, ignoreContext=None):
+ self.fields = Fields(self.__parent__.field.schema)
- self.mode = self.parentWidget.mode
- self.ignoreContext = self.parentWidget.ignoreContext
- self.ignoreRequest = self.parentWidget.ignoreRequest
-
-# XXX: I recommend to use the existing parent prefix as prefix for the new prefix
+ #update stuff from parent to be sure
+ self.mode = self.__parent__.mode
+ if ignoreContext is not None:
+ self.ignoreContext = ignoreContext
+ else:
+ self.ignoreContext = self.__parent__.ignoreContext
+ self.ignoreRequest = self.__parent__.ignoreRequest
+ if interfaces.IFormAware.providedBy(self.__parent__):
+ self.ignoreReadonly = self.parentForm.ignoreReadonly
-# prefix = util.expandPrefix(self.__parent__.prefix)
-# self.prefix = prefix + util.expandPrefix(
-# self.parentWidget.field.__name__)
- self.prefix = self.parentWidget.field.__name__
+ prefix = ''
+ if self.parentForm:
+ prefix = util.expandPrefix(self.parentForm.prefix) + \
+ util.expandPrefix(self.parentForm.widgets.prefix)
- if interfaces.IFormAware.providedBy(self.parentWidget):
- self.ignoreReadonly = self.parentWidget.form.ignoreReadonly
+ self.prefix = prefix+self.__parent__.field.__name__
super(ObjectSubForm, self).update()
@@ -90,10 +93,8 @@
factory = None
-# XXX: was x a debug hook?
def _fields(self):
- x = zope.schema.getFields(self.field.schema)
- return x
+ return zope.schema.getFields(self.field.schema)
def toWidgetValue(self, value):
"""Just dispatch it."""
@@ -104,21 +105,18 @@
def createObject(self, value):
#keep value passed, maybe some subclasses want it
+ #nasty: value here is the raw extracted from the widget's subform
+ #in the form of (value-dict, (error1, error2))
-# XXX: Are I'm correct the value is already an object?
-# if so, should we return the value?
-# if self.field.schema.providedBy(value):
-# return value
-
if self.factory is None:
name = self.field.schema.__module__+'.'+self.field.schema.__name__
- adapter = zope.component.queryMultiAdapter(
+ creator = zope.component.queryMultiAdapter(
(self.widget.context, self.widget.request,
self.widget.form, self.widget),
interfaces.IObjectFactory,
name=name)
- if adapter:
- obj = adapter.get(value)
+ if creator:
+ obj = creator(value)
else:
raise ValueError("No IObjectFactory adapter registered for %s" %
name)
@@ -137,20 +135,14 @@
if value[1]:
raise MultipleErrors(value[1])
-# XXX: check if this allways returns a new object instance. If so we need to
-# ensure that the existing instance doesn't get replaced. Because an existing
-# instance could provide some reference to other things we whould loose.
+ if (self.widget._value is not interfaces.NOVALUE
+ and not self.widget.subform.ignoreContext):
+ obj = self.widget._value
+ else:
+ obj = self.createObject(value)
-# probably we should do:
-# if self.field.schema.providedBy(value):
-# obj = value
-# else:
-# obj = self.createObject(value)
-#
-# Or are I'm wrong?
+ obj = self.field.schema(obj)
- obj = self.createObject(value)
-
for name, f in self._fields().items():
setattr(obj, name, value[0][name])
return obj
@@ -170,13 +162,8 @@
self.form = form
self.widget = widget
-# XXX: probably we should use __call__ instead of get and skip the value. Isn't
-# the value an existing object instance? Which means if we never replace
-# existing objects this should never get called within an existing value?
-# def __call__():
-# return self.factory()
-
- def get(self, value):
+ def __call__(self, value):
+ #value is the extracted data from the form
return self.factory()
def __repr__(self):
More information about the Checkins
mailing list