refactor error handling: get validation error information from a form attribute instead of req.data to avoid pb when multiple forms are displayed tls-sprint
authorsylvain.thenault@logilab.fr
Wed, 06 May 2009 18:13:32 +0200
branchtls-sprint
changeset 1710 8c717cc0b353
parent 1709 f7110f533d14
child 1711 182536159750
refactor error handling: get validation error information from a form attribute instead of req.data to avoid pb when multiple forms are displayed
web/form.py
web/formrenderers.py
web/views/editforms.py
--- a/web/form.py	Wed May 06 17:24:48 2009 +0200
+++ b/web/form.py	Wed May 06 18:13:32 2009 +0200
@@ -75,18 +75,22 @@
         # method on successful commit
         forminfo = self.req.get_session_data(sessionkey, pop=True)
         if forminfo:
-            self.req.data['formvalues'] = forminfo['values']
-            self.req.data['formerrors'] = errex = forminfo['errors']
-            self.req.data['displayederrors'] = set()
+            # XXX remove req.data assigment once cw.web.widget is killed
+            self.req.data['formvalues'] = self.form_previous_values = forminfo['values']
+            self.req.data['formerrors'] = self.form_valerror = forminfo['errors']
+            self.req.data['displayederrors'] = self.form_displayed_errors = set()
             # if some validation error occured on entity creation, we have to
             # get the original variable name from its attributed eid
-            foreid = errex.entity
+            foreid = self.form_valerror.entity
             for var, eid in forminfo['eidmap'].items():
                 if foreid == eid:
-                    errex.eid = var
+                    self.form_valerror.eid = var
                     break
             else:
-                errex.eid = foreid
+                self.form_valerror.eid = foreid
+        else:
+            self.form_previous_values = {}
+            self.form_valerror = None
 
     # XXX deprecated with new form system. Should disappear
 
@@ -166,11 +170,11 @@
 
         This method should be called once inlined field errors has been consumed
         """
-        errex = self.req.data.get('formerrors')
+        errex = self.req.data.get('formerrors') or self.form_valerror
         # get extra errors
         if errex is not None:
             errormsg = self.req._('please correct the following errors:')
-            displayed = self.req.data['displayederrors']
+            displayed = self.req.data.get('displayederrors') or self.form_displayed_errors
             errors = sorted((field, err) for field, err in errex.errors.items()
                             if not field in displayed)
             if errors:
@@ -333,9 +337,6 @@
         form_render()
         """
         self.context = context = {}
-        # on validation error, we get a dictionary of previously submitted
-        # values
-        self._previous_values = self.req.data.get('formvalues', {})
         # ensure rendervalues is a dict
         if rendervalues is None:
             rendervalues = {}
@@ -361,8 +362,8 @@
         value while those found in 3. and 4. are expected to be correctly typed.
         """
         qname = self.form_field_name(field)
-        if qname in self._previous_values:
-            value = self._previous_values[qname]
+        if qname in self.form_previous_values:
+            value = self.form_previous_values[qname]
         elif qname in self.req.form:
             value = self.req.form[qname]
         else:
@@ -385,10 +386,9 @@
 
     def form_field_error(self, field):
         """return validation error for widget's field, if any"""
-        errex = self.req.data.get('formerrors')
-        if errex and self._errex_match_field(errex, field):
-            self.req.data['displayederrors'].add(field.name)
-            return u'<span class="error">%s</span>' % errex.errors[field.name]
+        if self._field_has_error(field):
+            self.form_displayed_errors.add(field.name)
+            return u'<span class="error">%s</span>' % self.form_valerror.errors[field.name]
         return u''
 
     def form_field_format(self, field):
@@ -413,10 +413,10 @@
         """
         raise NotImplementedError
 
-    def _errex_match_field(self, errex, field):
+    def _field_has_error(self, field):
         """return true if the field has some error in given validation exception
         """
-        return field.name in errex.errors
+        return self.form_valerror and field.name in self.form_valerror.errors
 
 
 class EntityFieldsForm(FieldsForm):
@@ -443,10 +443,11 @@
         self.schema = self.edited_entity.schema
         self.vreg = self.edited_entity.vreg
 
-    def _errex_match_field(self, errex, field):
+    def _field_has_error(self, field):
         """return true if the field has some error in given validation exception
         """
-        return errex.eid == self.edited_entity.eid and field.name in errex.errors
+        return super(EntityFieldsForm, self)._field_has_error(field) \
+               and self.form_valerror.eid == self.edited_entity.eid
 
     def _relation_vocabulary(self, rtype, targettype, role,
                             limit=None, done=None):
--- a/web/formrenderers.py	Wed May 06 17:24:48 2009 +0200
+++ b/web/formrenderers.py	Wed May 06 18:13:32 2009 +0200
@@ -31,11 +31,12 @@
     +---------+
     """
     _options = ('display_fields', 'display_label', 'display_help',
-                'display_progress_div', 'button_bar_class')
+                'display_progress_div', 'table_class', 'button_bar_class')
     display_fields = None # None -> all fields
     display_label = True
     display_help = True
     display_progress_div = True
+    table_class = u'attributeForm'
     button_bar_class = u'formButtonBar'
 
     def __init__(self, **kwargs):
@@ -100,11 +101,11 @@
         This method should be called once inlined field errors has been consumed
         """
         req = form.req
-        errex = req.data.get('formerrors')
+        errex = form.form_valerror
         # get extra errors
         if errex is not None:
             errormsg = req._('please correct the following errors:')
-            displayed = req.data['displayederrors']
+            displayed = form.form_displayed_errors
             errors = sorted((field, err) for field, err in errex.errors.items()
                             if not field in displayed)
             if errors:
@@ -176,7 +177,7 @@
         return fields
 
     def _render_fields(self, fields, w, form):
-        w(u'<table class="attributeForm">')
+        w(u'<table class="%s">' % self.table_class)
         for field in fields:
             w(u'<tr>')
             if self.display_label:
@@ -255,7 +256,7 @@
     def _render_fields(self, fields, w, form):
         if form.is_subform:
             entity = form.edited_entity
-            values = form._previous_values
+            values = form.form_previous_values
             qeid = eid_param('eid', entity.eid)
             cbsetstate = "setCheckboxesState2('eid', %s, 'checked')" % html_escape(dumps(entity.eid))
             w(u'<tr class="%s">' % (entity.row % 2 and u'even' or u'odd'))
--- a/web/views/editforms.py	Wed May 06 17:24:48 2009 +0200
+++ b/web/views/editforms.py	Wed May 06 18:13:32 2009 +0200
@@ -124,7 +124,7 @@
         form.form_add_hidden(u'__maineid', entity.eid)
         renderer = FormRenderer(display_label=False, display_help=False,
                                 display_fields=[(rtype, role)],
-                                button_bar_class='buttonbar',
+                                table_class='', button_bar_class='buttonbar',
                                 display_progress_div=False)
         self.w(tags.div(value, klass='editableField', id=divid,
                         ondblclick=self.ondblclick % event_data))
@@ -327,7 +327,7 @@
 
     def add_hiddens(self, form, entity, peid, rtype, role):
         # to ease overriding (see cubes.vcsfile.views.forms for instance)
-        if self.keep_entity(entity, peid, rtype):
+        if self.keep_entity(form, entity, peid, rtype):
             if entity.has_eid():
                 rval = entity.eid
             else:
@@ -336,14 +336,13 @@
         form.form_add_hidden(name='%s:%s' % (rtype, peid), value=entity.eid,
                              id='rel-%s-%s-%s'  % (peid, rtype, entity.eid))
 
-    def keep_entity(self, entity, peid, rtype):
+    def keep_entity(self, form, entity, peid, rtype):
         if not entity.has_eid():
             return True
         # are we regenerating form because of a validation error ?
-        erroneous_post = self.req.data.get('formvalues')
         if erroneous_post:
-            cdvalues = self.req.list_form_param('%s:%s' % (rtype, peid),
-                                                erroneous_post)
+            cdvalues = self.req.list_form_param(eid_param(rtype, peid),
+                                                form.form_previous_values)
             if unicode(entity.eid) not in cdvalues:
                 return False
         return True