[form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Tue, 23 Feb 2010 17:32:31 +0100
branchstable
changeset 4668 9f82f81bf13d
parent 4667 6c8eccb1b695
child 4669 2a77a0d9075f
[form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings * move __init__ code from FieldsForm to Form. Must behaviour here should actually be in the Form base class * avoid buggy duplicated call to restore_previous_post * move some code that was in the form renderer to the form'__init__ method (__redirectpath & __form_id hidden input handling)) * 'formvid' should now be specified on form selection, not on form rendering
web/form.py
web/views/editforms.py
web/views/formrenderers.py
web/views/forms.py
--- a/web/form.py	Thu Feb 18 14:30:23 2010 +0100
+++ b/web/form.py	Tue Feb 23 17:32:31 2010 +0100
@@ -15,7 +15,7 @@
 from cubicweb.appobject import AppObject
 from cubicweb.view import NOINDEX, NOFOLLOW
 from cubicweb import tags
-from cubicweb.web import stdmsgs, httpcache, formfields
+from cubicweb.web import stdmsgs, httpcache, formfields, controller
 
 
 class FormViewMixIn(object):
@@ -69,12 +69,42 @@
     __metaclass__ = metafieldsform
     __registry__ = 'forms'
 
+    internal_fields = ('__errorurl',) + controller.NAV_FORM_PARAMETERS
+
     parent_form = None
     force_session_key = None
+    domid = 'form'
+    copy_nav_params = False
 
-    def __init__(self, req, rset, **kwargs):
-        super(Form, self).__init__(req, rset=rset, **kwargs)
-        self.restore_previous_post(self.session_key())
+    def __init__(self, req, rset=None, row=None, col=None,
+                 submitmsg=None, mainform=True, **kwargs):
+        super(Form, self).__init__(req, rset=rset, row=row, col=col)
+        self.fields = list(self.__class__._fields_)
+        self.add_hidden(u'__form_id', kwargs.pop('formvid', self.__regid__))
+        for key, val in kwargs.iteritems():
+            if key in controller.NAV_FORM_PARAMETERS:
+                self.add_hidden(key, val)
+            elif key == 'redirect_path':
+                self.add_hidden(u'__redirectpath', val)
+            elif hasattr(self.__class__, key) and not key[0] == '_':
+                setattr(self, key, val)
+            else:
+                self.cw_extra_kwargs[key] = val
+            # skip other parameters, usually given for selection
+            # (else write a custom class to handle them)
+        if mainform:
+            self.add_hidden(u'__errorurl', self.session_key())
+            self.add_hidden(u'__domid', self.domid)
+            self.restore_previous_post(self.session_key())
+        # XXX why do we need two different variables (mainform and copy_nav_params ?)
+        if self.copy_nav_params:
+            for param in controller.NAV_FORM_PARAMETERS:
+                if not param in kwargs:
+                    value = req.form.get(param)
+                    if value:
+                        self.add_hidden(param, value)
+        if submitmsg is not None:
+            self.add_hidden(u'__message', submitmsg)
 
     @property
     def root_form(self):
--- a/web/views/editforms.py	Thu Feb 18 14:30:23 2010 +0100
+++ b/web/views/editforms.py	Tue Feb 23 17:32:31 2010 +0100
@@ -101,7 +101,7 @@
                                              entity=entity,
                                              submitmsg=self.submited_message())
         self.init_form(form, entity)
-        self.w(form.render(formvid=u'edition'))
+        self.w(form.render())
 
     def init_form(self, form, entity):
         """customize your form before rendering here"""
@@ -234,10 +234,6 @@
         """a view to edit multiple entities of the same type the first column
         should be the eid
         """
-        #self.form_title(entity)
-        form = self._cw.vreg['forms'].select(self.__regid__, self._cw,
-                                             rset=self.cw_rset,
-                                             copy_nav_params=True)
         # XXX overriding formvid (eg __form_id) necessary to make work edition:
         # the edit controller try to select the form with no rset but
         # entity=entity, and use this form to edit the entity. So we want
@@ -245,7 +241,11 @@
         # side effect. Maybe we should provide another variable optinally
         # telling which form the edit controller should select (eg difffers
         # between html generation / post handling form)
-        self.w(form.render(formvid='edition'))
+        form = self._cw.vreg['forms'].select(self.__regid__, self._cw,
+                                             rset=self.cw_rset,
+                                             copy_nav_params=True,
+                                             formvid='edition')
+        self.w(form.render())
 
 
 # click and edit handling ('reledit') ##########################################
--- a/web/views/formrenderers.py	Thu Feb 18 14:30:23 2010 +0100
+++ b/web/views/formrenderers.py	Tue Feb 23 17:32:31 2010 +0100
@@ -85,10 +85,6 @@
         if self.display_progress_div:
             w(u'<div id="progress">%s</div>' % self._cw._('validating...'))
         w(u'<fieldset>')
-        w(tags.input(type=u'hidden', name=u'__form_id',
-                     value=values.get('formvid', form.__regid__)))
-        if form.redirect_path:
-            w(tags.input(type='hidden', name='__redirectpath', value=form.redirect_path))
         self.render_fields(w, form, values)
         self.render_buttons(w, form)
         w(u'</fieldset>')
--- a/web/views/forms.py	Thu Feb 18 14:30:23 2010 +0100
+++ b/web/views/forms.py	Tue Feb 23 17:32:31 2010 +0100
@@ -58,54 +58,20 @@
     """
     __regid__ = 'base'
 
-    internal_fields = ('__errorurl',) + NAV_FORM_PARAMETERS
 
     # attributes overrideable by subclasses or through __init__
     needs_js = ('cubicweb.ajax.js', 'cubicweb.edition.js',)
     needs_css = ('cubicweb.form.css',)
-    domid = 'form'
     action = None
     onsubmit = "return freezeFormButtons('%(domid)s');"
     cssclass = None
     cssstyle = None
     cwtarget = None
     redirect_path = None
-    copy_nav_params = False
     form_buttons = None
     form_renderer_id = 'default'
     fieldsets_in_order = None
 
-    def __init__(self, req, rset=None, row=None, col=None,
-                 submitmsg=None, mainform=True,
-                 **kwargs):
-        super(FieldsForm, self).__init__(req, rset=rset, row=row, col=col)
-        self.fields = list(self.__class__._fields_)
-        for key, val in kwargs.items():
-            if key in NAV_FORM_PARAMETERS:
-                self.add_hidden(key, val)
-            elif hasattr(self.__class__, key) and not key[0] == '_':
-                setattr(self, key, val)
-            else:
-                self.cw_extra_kwargs[key] = val
-            # skip other parameters, usually given for selection
-            # (else write a custom class to handle them)
-        if mainform:
-            self.add_hidden('__errorurl', self.session_key())
-            self.add_hidden('__domid', self.domid)
-            self.restore_previous_post(self.session_key())
-
-        # XXX why do we need two different variables (mainform and copy_nav_params ?)
-        if self.copy_nav_params:
-            for param in NAV_FORM_PARAMETERS:
-                if not param in kwargs:
-                    value = req.form.get(param)
-                    if value:
-                        self.add_hidden(param, value)
-        if submitmsg is not None:
-            self.add_hidden('__message', submitmsg)
-        if 'domid' in kwargs:# session key changed
-            self.restore_previous_post(self.session_key())
-
     @property
     def needs_multipart(self):
         """true if the form needs enctype=multipart/form-data"""