[Zope3-checkins] CVS: Zope3/lib/python/Zope/App/Forms/Views/Browser - FormView.py:1.10 IForm.py:1.7 Widget.py:1.7

Martijn Faassen m.faassen@vet.uu.nl
Wed, 4 Sep 2002 09:44:54 -0400


Update of /cvs-repository/Zope3/lib/python/Zope/App/Forms/Views/Browser
In directory cvs.zope.org:/tmp/cvs-serv31848/python/Zope/App/Forms/Views/Browser

Modified Files:
	FormView.py IForm.py Widget.py 
Log Message:
Refactored Forms (and Schema).

  * A FormView now specifies a single schema explicitly as the 'schema'
    (class) attribute. A schema is simply an interface with Field attributes
    on it.

  * The FormView code now uses the Schema package more for its own
    implementation, instead of trying to reimplement things itself.

  * got rid of the 'id' attribute for fields. Fields now already know what
    name they have, because of the Interface package setting __name__.
    Use getName() to get the field name.



=== Zope3/lib/python/Zope/App/Forms/Views/Browser/FormView.py 1.9 => 1.10 ===
--- Zope3/lib/python/Zope/App/Forms/Views/Browser/FormView.py:1.9	Wed Jul 24 06:53:48 2002
+++ Zope3/lib/python/Zope/App/Forms/Views/Browser/FormView.py	Wed Sep  4 09:44:23 2002
@@ -14,12 +14,11 @@
 """
 $Id$
 """
-from Interface.Implements import flattenInterfaces
 from Schema.IField import IField
 from Schema.Exceptions import StopValidation, ValidationError, \
      ConversionError, ValidationErrorsAll, ConversionErrorsAll
-
-from Zope.Proxy.ContextWrapper import ContextWrapper
+from Schema import getFields, validateMappingAll
+#from Zope.Proxy.ContextWrapper import ContextWrapper
 from Zope.ComponentArchitecture import getView
 from Zope.Proxy.ProxyIntrospection import removeAllProxies
 from Zope.Publisher.Browser.BrowserView import BrowserView
@@ -34,122 +33,82 @@
 
     form = None
     custom_widgets = None
+    schema = None
     fields_order = None
 
     def getFields(self):
         'See Zope.App.Forms.Views.Browser.IForm.IReadForm'
-        context = removeAllProxies(self.context)
-        interfaces = context.__implements__
-        if isinstance(interfaces, (tuple, list)):
-            interfaces = flattenInterfaces(interfaces)
+        fields = getFields(self.schema)
+        fields_order = self.fields_order
+        if fields_order:
+            return [fields[name] for name in fields_order]
         else:
-            interfaces = (interfaces,)
-        request = self.request
-        fields = {}
-        for interface in interfaces:
-            for name in interface.names(1):
-                attr = interface.getDescriptionFor(name)
-                if IField.isImplementedBy(attr):
-                    # Give the field a context before adding, so they
-                    # know how to retrieve data.
-                    fields[name] = ContextWrapper(attr, self.context,
-                                                  name=name)
-
-        if self.fields_order is None:
             return fields.values()
-
-        result = []
-        for id in self.fields_order:
-            result.append(fields[id])
-        return result
-
-
-    def getField(self, id):
+        
+    def getField(self, name):
         'See Zope.App.Forms.Views.Browser.IForm.IReadForm'
-        # XXX This needs to be optimized!
-        field = None
-        for f in self.getFields():
-            if f.id == id:
-                field = f
-                break
-        if field is None:
-            raise KeyError, 'Field id "%s" does not exist.' %id
+        field = self.schema.getDescriptionFor(name)
+        assert IField.isImplementedBy(field)
         return field
 
-
-    def getWidgetForFieldId(self, id):
+    def getWidgetForFieldName(self, name):
         'See Zope.App.Forms.Views.Browser.IForm.IReadForm'
-        field = self.getField(id)
-        return self.getWidgetForField(field)
-
+        return self.getWidgetForField(self.getField(name))
 
     def getWidgetForField(self, field):
         'See Zope.App.Forms.Views.Browser.IForm.IReadForm'
-        if self.custom_widgets is not None and \
-           field.id in self.custom_widgets.keys():
-            return self.custom_widgets[field.id](field, self.request)
+        name = field.getName()
+        if (self.custom_widgets is not None and
+            self.custom_widgets.has_key(name)):
+            return self.custom_widgets[name](field, self.request)
         return getView(field, 'widget', self.request)
 
-
     def renderField(self, field, useRequest=0):
         'See Zope.App.Forms.Views.Browser.IForm.IReadForm'
         widget = self.getWidgetForField(field)
         value = None
         if useRequest:
-            value = self.request.form.get('field_' + field.id)
+            value = self.request.form.get('field_' + field.getName())
         if value is None:
-            value = getattr(self.context, field.id)
+            value = getattr(self.context, field.getName())
         return widget.render(value)
 
-
     def getAllRawFieldData(self):
         """Returns field data retrieved from request."""
         request = self.request
         data = {}
         for field in self.getFields():
-            raw_data = request.form.get('field_' + field.id)
-            data[field] = raw_data
+            name = field.getName()
+            raw_data = request.form.get('field_' + name)
+            data[name] = raw_data
         return data
 
-
-    def convertAllFieldData(self, mapping):
+    def convertAllFieldData(self, raw_data):
         """Convert the raw data into valid objects."""
-        data = {}
+        result = {}
         errors = []
-        for field in mapping:
-            widget = self.getWidgetForField(field)
+        for name, value in raw_data.iteritems():
+            widget = self.getWidgetForFieldName(name)
             try:
-                data[field] = widget.convert(mapping[field])
+                result[name] = widget.convert(value)
             except ConversionError, error:
-                errors.append((field, error))
+                errors.append((name, error))
 
         if errors:
             raise ConversionErrorsAll, errors
-        
-        return data
-            
 
-    def validateAllFieldData(self, mapping):
+        return result
+            
+    def validateAllFieldData(self, data):
         """Validate all the data."""
-        errors = []
-        for field in mapping:
-            try:
-                field.validate(mapping[field])
-            except ValidationError, error:
-                errors.append((field, error))
-
-        if errors:
-            raise ValidationErrorsAll, errors
+        validateMappingAll(self.schema, data)
 
-
-    def storeAllDataInContext(self, mapping):
+    def storeAllDataInContext(self, data):
         """Store the data back into the context object."""
         context = removeAllProxies(self.context)
-        for field in mapping:
-            value = mapping[field]
-            if value != getattr(context, field.id):
-                setattr(context, field.id, value)
-
+        for name, value in data.iteritems():
+            if value != getattr(context, name):
+                setattr(context, name, value)
 
     def saveValuesInContext(self):
         'See Zope.App.Forms.Views.Browser.IForm.IWriteForm'
@@ -157,7 +116,6 @@
         data = self.convertAllFieldData(data)
         self.validateAllFieldData(data)
         self.storeAllDataInContext(data)
-
 
     def action(self):
         'See Zope.App.Forms.Views.Browser.IForm.IWriteForm'


=== Zope3/lib/python/Zope/App/Forms/Views/Browser/IForm.py 1.6 => 1.7 ===
--- Zope3/lib/python/Zope/App/Forms/Views/Browser/IForm.py:1.6	Wed Jul 24 06:53:48 2002
+++ Zope3/lib/python/Zope/App/Forms/Views/Browser/IForm.py	Wed Sep  4 09:44:23 2002
@@ -24,6 +24,9 @@
     form = Attribute(
         """The form template. Usually a Page Template.""")
 
+    schema = Attribute(
+        """The schema this form should be constructed from.""")
+    
     custom_widgets = Attribute(
         """A dictionary that holds custom widgets for various fields.""")
 
@@ -39,15 +42,15 @@
     def getFields():
         """Get all the fields that need input from the content object."""
 
-    def getField(id):
-        """Get a field by id from the content object schemas."""
+    def getField(name):
+        """Get a field by name from the content object schemas."""
 
-    def getWidgetForFieldId(id):
-        """Lookup the widget of the field having id."""
+    def getWidgetForFieldName(name):
+        """Lookup the widget of the field by name."""
 
     def getWidgetForField(field):
         """Return the correct widget instance for a field. This method
-        consildates the custom_widgets attribute """
+        consults the custom_widgets attribute """
 
     def renderField(field):
         """Render a field using the widgets."""


=== Zope3/lib/python/Zope/App/Forms/Views/Browser/Widget.py 1.6 => 1.7 ===
--- Zope3/lib/python/Zope/App/Forms/Views/Browser/Widget.py:1.6	Wed Jul 24 06:53:48 2002
+++ Zope3/lib/python/Zope/App/Forms/Views/Browser/Widget.py	Wed Sep  4 09:44:23 2002
@@ -49,7 +49,7 @@
         'See Zope.App.Forms.Views.Browser.IBrowserWidget.IBrowserWidget'
         return renderElement(self.getValue('tag'),
                              type = self.getValue('type'),
-                             name = self.context.id,
+                             name = self.context.getName(),
                              value = value,
                              cssClass = self.getValue('cssClass'),
                              extra = self.getValue('extra'))
@@ -58,7 +58,7 @@
         'See Zope.App.Forms.Views.Browser.IBrowserWidget.IBrowserWidget'
         return renderElement(self.getValue('tag'),
                              type = 'hidden',
-                             name = self.context.id,
+                             name = self.context.getName(),
                              value = value,
                              cssClass = self.getValue('cssClass'),
                              extra = self.getValue('extra'))
@@ -78,14 +78,14 @@
         if value:
             return renderElement(self.getValue('tag'),
                                  type = self.getValue('type'),
-                                 name = self.context.id,
+                                 name = self.context.getName(),
                                  checked = None,
                                  cssClass = self.getValue('cssClass'),
                                  extra = self.getValue('extra'))
         else:
             return renderElement(self.getValue('tag'),
                                  type = self.getValue('type'),
-                                 name = self.context.id,
+                                 name = self.context.getName(),
                                  cssClass = self.getValue('cssClass'),
                                  size = self.getValue('displayWidth'),
                                  extra = self.getValue('extra'))
@@ -106,7 +106,7 @@
         if displayMaxWidth > 0:
             return renderElement(self.getValue('tag'),
                                  type = self.getValue('type'),
-                                 name = self.context.id,
+                                 name = self.context.getName(),
                                  value = value,
                                  cssClass = self.getValue('cssClass'),
                                  size = self.getValue('displayWidth'),
@@ -115,7 +115,7 @@
         else:
             return renderElement(self.getValue('tag'),
                                  type = self.getValue('type'),
-                                 name = self.context.id,
+                                 name = self.context.getName(),
                                  value = value,
                                  cssClass = self.getValue('cssClass'),
                                  size = self.getValue('displayWidth'),
@@ -135,7 +135,7 @@
     def render(self, value):
         'See Zope.App.Forms.Views.Browser.IBrowserWidget.IBrowserWidget'
         return renderElement("textarea",
-                             name=self.context.id,
+                             name=self.context.getName(),
                              cssClass=self.getValue('cssClass'),
                              cols=self.getValue('width'),
                              rows=self.getValue('height'),
@@ -159,7 +159,7 @@
         if displayMaxWidth > 0:
             return renderElement(self.getValue('tag'),
                                  type = self.getValue('type'),
-                                 name = self.context.id,
+                                 name = self.context.getName(),
                                  cssClass = self.getValue('cssClass'),
                                  size = self.getValue('displayWidth'),
                                  maxlength = displayMaxWidth,
@@ -167,7 +167,7 @@
         else:
             return renderElement(self.getValue('tag'),
                                  type = self.getValue('type'),
-                                 name = self.context.id,
+                                 name = self.context.getName(),
                                  cssClass = self.getValue('cssClass'),
                                  size = self.getValue('displayWidth'),
                                  extra = self.getValue('extra'))
@@ -185,7 +185,7 @@
     firstItem = 0    
 
     def renderItems(self, value):
-        name = self.context.id
+        name = self.context.getName()
         # get items
         items = self.context.items
         if callable(items):
@@ -236,7 +236,7 @@
         'See Zope.App.Forms.Views.Browser.IBrowserWidget.IBrowserWidget'
         renderedItems = self.renderItems(value)
         return renderElement('select',
-                              name=self.context.id,
+                              name=self.context.getName(),
                               cssClass=self.getValue('cssClass'),
                               size=self.getValue('size'),
                               contents="\n".join(renderedItems),
@@ -294,7 +294,7 @@
 
         if not isinstance(value, ListTypes):
             value = [value]
-        name = self.context.id
+        name = self.context.getName()
         items = self.context.items
         if callable(items):
             items = items()
@@ -333,7 +333,7 @@
         'See Zope.App.Forms.Views.Browser.IBrowserWidget.IBrowserWidget'
         rendered_items = self.renderItems(value)
         return renderElement('select',
-                              name=self.context.id,
+                              name=self.context.getName(),
                               multiple=None,
                               cssClass=self.getValue('cssClass'),
                               size=self.getValue('size'),