[Checkins] SVN: z3c.form/trunk/ - Changes: around objectwidget

Adam Groszer agroszer at gmail.com
Tue Nov 25 09:33:06 EST 2008


Log message for revision 93344:
  - Changes: around objectwidget
    - zcml objectWidgetTemplate to be able to register widget templates for specific field schemas
    - subwidgets prefix will come from the main-widget
    - subform discriminator on field.schema did not work
            
  - Fixes: MultiWidget:
    - setting (sub)widgets early
    - setting subwidgets.form
  

Changed:
  U   z3c.form/trunk/CHANGES.txt
  U   z3c.form/trunk/src/z3c/form/meta.zcml
  U   z3c.form/trunk/src/z3c/form/object.py
  U   z3c.form/trunk/src/z3c/form/widget.py
  U   z3c.form/trunk/src/z3c/form/zcml.py

-=-
Modified: z3c.form/trunk/CHANGES.txt
===================================================================
--- z3c.form/trunk/CHANGES.txt	2008-11-25 14:25:37 UTC (rev 93343)
+++ z3c.form/trunk/CHANGES.txt	2008-11-25 14:33:06 UTC (rev 93344)
@@ -5,6 +5,16 @@
 Version 2.0.0 (2008-??-??)
 --------------------------
 
+- Changes: around objectwidget
+  - zcml objectWidgetTemplate to be able to register widget templates for
+    specific field schemas
+  - subwidgets prefix will come from the main-widget
+  - subform discriminator on field.schema did not work
+
+- Fixes: MultiWidget:
+  - setting (sub)widgets early
+  - setting subwidgets.form
+
 - Feature: When no file is specified in the file upload widget, instead of
   overwriting the value with a missing one, the old data is retained.
 

Modified: z3c.form/trunk/src/z3c/form/meta.zcml
===================================================================
--- z3c.form/trunk/src/z3c/form/meta.zcml	2008-11-25 14:25:37 UTC (rev 93343)
+++ z3c.form/trunk/src/z3c/form/meta.zcml	2008-11-25 14:33:06 UTC (rev 93344)
@@ -10,7 +10,12 @@
         handler=".zcml.widgetTemplateDirective"
         />
 
+    <meta:directive
+        name="objectWidgetTemplate"
+        schema=".zcml.IObjectWidgetTemplateDirective"
+        handler=".zcml.objectWidgetTemplateDirective"
+        />
+
   </meta:directives>
 
 </configure>
-

Modified: z3c.form/trunk/src/z3c/form/object.py
===================================================================
--- z3c.form/trunk/src/z3c/form/object.py	2008-11-25 14:25:37 UTC (rev 93343)
+++ z3c.form/trunk/src/z3c/form/object.py	2008-11-25 14:33:06 UTC (rev 93344)
@@ -23,6 +23,9 @@
 import zope.event
 import zope.lifecycleevent
 from zope.security.proxy import removeSecurityProxy
+from zope.pagetemplate.interfaces import IPageTemplate
+
+from z3c.pt import compat as viewpagetemplatefile
 from z3c.form.converter import BaseDataConverter
 
 from z3c.form import form, interfaces, util, widget
@@ -81,12 +84,14 @@
         if interfaces.IFormAware.providedBy(self.__parent__):
             self.ignoreReadonly = self.parentForm.ignoreReadonly
 
-        prefix = ''
-        if self.parentForm:
-            prefix = util.expandPrefix(self.parentForm.prefix) + \
-                util.expandPrefix(self.parentForm.widgets.prefix)
+        #prefix = ''
+        #if self.parentForm:
+        #    prefix = util.expandPrefix(self.parentForm.prefix) + \
+        #        util.expandPrefix(self.parentForm.widgets.prefix)
+        #
+        #self.prefix = prefix+self.__parent__.field.__name__
 
-        self.prefix = prefix+self.__parent__.field.__name__
+        self.prefix = self.__parent__.name
 
         self.setupFields()
 
@@ -151,6 +156,8 @@
                 obj = dm.get()
             except KeyError:
                 obj = self.createObject(value)
+            except AttributeError:
+                obj = self.createObject(value)
 
         obj = self.field.schema(obj)
 
@@ -194,7 +201,7 @@
 
         self.subform = zope.component.getMultiAdapter(
             (content, self.request, self.context,
-             form, self, self.field, schema),
+             form, self, self.field, makeDummyObject(schema)),
             interfaces.ISubformFactory)()
 
     def updateWidgets(self, setErrors=True):
@@ -221,6 +228,10 @@
         """This invokes updateWidgets on any value change e.g. update/extract."""
         def get(self):
             return self.extract(setErrors=True)
+            #value = {}
+            #for name in zope.schema.getFieldNames(self.field.schema):
+            #    value[name] = self.subform.widgets[name].value
+            #return value
         def set(self, value):
             self._value = value
             # ensure that we apply our new values to the widgets
@@ -239,6 +250,7 @@
                 #while we're updating
                 if self._updating:
                     return default
+
                 raise MultipleErrors(errors)
 
             return value
@@ -246,7 +258,52 @@
         else:
             return default
 
+    def render(self):
+        """See z3c.form.interfaces.IWidget."""
+        template = self.template
+        if template is None:
+            template = zope.component.queryMultiAdapter(
+                (self.context, self.request, self.form, self.field, self,
+                 makeDummyObject(self.field.schema)),
+                IPageTemplate, name=self.mode)
+            if template is None:
+                return super(ObjectWidget, self).render()
+        return template(self)
 
+######## make dummy objects providing a given interface to support
+######## discriminating on field.schema
+
+class DummyObject(object):
+    zope.interface.implements(zope.interface.Interface)
+
+def makeDummyObject(iface):
+    dummy = DummyObject()
+    if iface is not None:
+        zope.interface.directlyProvides(dummy, iface)
+    return dummy
+
+######## special template factory that takes the field.schema into account
+
+class ObjectWidgetTemplateFactory(object):
+    """Widget template factory."""
+
+    def __init__(self, filename, contentType='text/html',
+                 context=None, request=None, view=None,
+                 field=None, widget=None, schema=None):
+        self.template = viewpagetemplatefile.ViewPageTemplateFile(
+            filename, content_type=contentType)
+        zope.component.adapter(
+            util.getSpecification(context),
+            util.getSpecification(request),
+            util.getSpecification(view),
+            util.getSpecification(field),
+            util.getSpecification(widget),
+            util.getSpecification(schema))(self)
+        zope.interface.implementer(IPageTemplate)(self)
+
+    def __call__(self, context, request, view, field, widget, schema):
+        return self.template
+
 ######## default adapters
 
 class SubformAdapter(object):
@@ -274,7 +331,6 @@
         self.schema = schema
 
     def __call__(self):
-        #value is the extracted data from the form
         obj = self.factory(self.context, self.request, self.widget)
         return obj
 

Modified: z3c.form/trunk/src/z3c/form/widget.py
===================================================================
--- z3c.form/trunk/src/z3c/form/widget.py	2008-11-25 14:25:37 UTC (rev 93343)
+++ z3c.form/trunk/src/z3c/form/widget.py	2008-11-25 14:33:06 UTC (rev 93344)
@@ -245,9 +245,13 @@
     # you set showLabel to False or use another template for disable (sub)
     # widget labels
     showLabel = True
-    widgets = []
+    widgets = None
     _value = []
 
+    def __init__(self, request):
+        super(MultiWidget, self).__init__(request)
+        self.widgets = []
+
     @property
     def counterName(self):
         return '%s.count' % self.name
@@ -268,6 +272,11 @@
             interfaces.IFieldWidget)
         widget.name = name
         widget.id = id
+        #set widget.form (objectwidget needs this)
+        if interfaces.IFormAware.providedBy(self):
+            widget.form = self.form
+            zope.interface.alsoProvides(
+                widget, interfaces.IFormAware)
         widget.update()
         return widget
 
@@ -281,11 +290,11 @@
     def applyValue(self, widget, value=interfaces.NOVALUE):
         """Validate and apply value to given widget.
 
-        This method get called on any multi widget vaue change and is
-        responsible for validate the given value and setup an error message.
+        This method gets called on any multi widget value change and is
+        responsible for validating the given value and setup an error message.
 
         This is internal apply value and validation process is needed because
-        nothing outside this mutli widget does know something about our
+        nothing outside this multi widget does know something about our
         internal sub widgets.
         """
         if value is not interfaces.NOVALUE:
@@ -348,7 +357,7 @@
         # We have to setup the widgets for extract their values, because we
         # don't know how to do this for every field without the right widgets.
         # Later we will setup the widgets based on this values. This is needed
-        # because we probably set a new value in the fornm for our multi widget
+        # because we probably set a new value in the form for our multi widget
         # which whould generate a different set of widgets.
         if self.request.get(self.counterName) is None:
             # counter marker not found

Modified: z3c.form/trunk/src/z3c/form/zcml.py
===================================================================
--- z3c.form/trunk/src/z3c/form/zcml.py	2008-11-25 14:25:37 UTC (rev 93343)
+++ z3c.form/trunk/src/z3c/form/zcml.py	2008-11-25 14:33:06 UTC (rev 93344)
@@ -29,6 +29,7 @@
 from z3c.form import interfaces
 from z3c.form.i18n import MessageFactory as _
 from z3c.form.widget import WidgetTemplateFactory
+from z3c.form.object import ObjectWidgetTemplateFactory
 
 
 class IWidgetTemplateDirective(zope.interface.Interface):
@@ -83,7 +84,14 @@
         default='text/html',
         required=False)
 
+class IObjectWidgetTemplateDirective(IWidgetTemplateDirective):
+    schema = zope.configuration.fields.GlobalObject(
+        title=_('Schema'),
+        description=_('The schema of the field for which the template should be available'),
+        default=zope.interface.Interface,
+        required=False)
 
+
 def widgetTemplateDirective(
     _context, template, for_=zope.interface.Interface,
     layer=IDefaultBrowserLayer, view=None, field=None, widget=None,
@@ -100,3 +108,22 @@
     # register the template
     zope.component.zcml.adapter(_context, (factory,), IPageTemplate,
         (for_, layer, view, field, widget), name=mode)
+
+
+def objectWidgetTemplateDirective(
+    _context, template, for_=zope.interface.Interface,
+    layer=IDefaultBrowserLayer, view=None, field=None, widget=None,
+    schema=None,
+    mode=interfaces.INPUT_MODE, contentType='text/html'):
+
+    # Make sure that the template exists
+    template = os.path.abspath(str(_context.path(template)))
+    if not os.path.isfile(template):
+        raise ConfigurationError("No such file", template)
+
+    factory = ObjectWidgetTemplateFactory(template, contentType)
+    zope.interface.directlyProvides(factory, IPageTemplate)
+
+    # register the template
+    zope.component.zcml.adapter(_context, (factory,), IPageTemplate,
+        (for_, layer, view, field, widget, schema), name=mode)



More information about the Checkins mailing list