web/form.py
changeset 3998 94cc7cad3d2d
parent 3524 a3431f4e2f40
parent 3925 25d5830b9531
child 4003 b9436fe77c9e
--- a/web/form.py	Mon Nov 23 14:13:53 2009 +0100
+++ b/web/form.py	Thu Dec 03 17:17:43 2009 +0100
@@ -36,6 +36,163 @@
         return False
 
 
+<<<<<<< /home/syt/src/fcubicweb/cubicweb/web/form.py
+=======
+# XXX should disappear
+class FormMixIn(object):
+    """abstract form mix-in
+    XXX: you should inherit from this FIRST (obscure pb with super call)
+    """
+    force_session_key = None
+
+    def session_key(self):
+        """return the key that may be used to store / retreive data about a
+        previous post which failed because of a validation error
+        """
+        if self.force_session_key is None:
+            return '%s#%s' % (self.req.url(), self.domid)
+        return self.force_session_key
+
+    def restore_previous_post(self, sessionkey):
+        # get validation session data which may have been previously set.
+        # deleting validation errors here breaks form reloading (errors are
+        # no more available), they have to be deleted by application's publish
+        # method on successful commit
+        forminfo = self.req.get_session_data(sessionkey, pop=True)
+        if forminfo:
+            # 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 = self.form_valerror.entity
+            for var, eid in forminfo['eidmap'].items():
+                if foreid == eid:
+                    self.form_valerror.eid = var
+                    break
+            else:
+                self.form_valerror.eid = foreid
+        else:
+            self._form_previous_values = {}
+            self._form_valerror = None
+
+    @property
+    def form_previous_values(self):
+        if self.parent_form is None:
+            return self._form_previous_values
+        return self.parent_form.form_previous_values
+
+    @property
+    def form_valerror(self):
+        if self.parent_form is None:
+            return self._form_valerror
+        return self.parent_form.form_valerror
+
+    # XXX deprecated with new form system. Should disappear
+
+    domid = 'entityForm'
+    category = 'form'
+    controller = 'edit'
+    http_cache_manager = httpcache.NoHTTPCacheManager
+    add_to_breadcrumbs = False
+
+    def html_headers(self):
+        """return a list of html headers (eg something to be inserted between
+        <head> and </head> of the returned page
+
+        by default forms are neither indexed nor followed
+        """
+        return [NOINDEX, NOFOLLOW]
+
+    def linkable(self):
+        """override since forms are usually linked by an action,
+        so we don't want them to be listed by appli.possible_views
+        """
+        return False
+
+
+    def button(self, label, klass='validateButton', tabindex=None, **kwargs):
+        if tabindex is None:
+            tabindex = self.req.next_tabindex()
+        return tags.input(value=label, klass=klass, **kwargs)
+
+    def action_button(self, label, onclick=None, __action=None, **kwargs):
+        if onclick is None:
+            onclick = "postForm('__action_%s', \'%s\', \'%s\')" % (
+                __action, label, self.domid)
+        return self.button(label, onclick=onclick, **kwargs)
+
+    def button_ok(self, label=None, type='submit', name='defaultsubmit',
+                  **kwargs):
+        label = self.req._(label or stdmsgs.BUTTON_OK).capitalize()
+        return self.button(label, name=name, type=type, **kwargs)
+
+    def button_apply(self, label=None, type='button', **kwargs):
+        label = self.req._(label or stdmsgs.BUTTON_APPLY).capitalize()
+        return self.action_button(label, __action='apply', type=type, **kwargs)
+
+    def button_delete(self, label=None, type='button', **kwargs):
+        label = self.req._(label or stdmsgs.BUTTON_DELETE).capitalize()
+        return self.action_button(label, __action='delete', type=type, **kwargs)
+
+    def button_cancel(self, label=None, type='button', **kwargs):
+        label = self.req._(label or stdmsgs.BUTTON_CANCEL).capitalize()
+        return self.action_button(label, __action='cancel', type=type, **kwargs)
+
+    def button_reset(self, label=None, type='reset', name='__action_cancel',
+                     **kwargs):
+        label = self.req._(label or stdmsgs.BUTTON_CANCEL).capitalize()
+        return self.button(label, type=type, **kwargs)
+
+    def need_multipart(self, entity, categories=('primary', 'secondary')):
+        """return a boolean indicating if form's enctype should be multipart
+        """
+        for rschema, _, x in entity.relations_by_category(categories):
+            if entity.get_widget(rschema, x).need_multipart:
+                return True
+        # let's find if any of our inlined entities needs multipart
+        for rschema, targettypes, x in entity.relations_by_category('inlineview'):
+            assert len(targettypes) == 1, \
+                   "I'm not able to deal with several targets and inlineview"
+            ttype = targettypes[0]
+            inlined_entity = self.vreg.etype_class(ttype)(self.req, None, None)
+            for irschema, _, x in inlined_entity.relations_by_category(categories):
+                if inlined_entity.get_widget(irschema, x).need_multipart:
+                    return True
+        return False
+
+    def error_message(self):
+        """return formatted error message
+
+        This method should be called once inlined field errors has been consumed
+        """
+        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.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:
+                if len(errors) > 1:
+                    templstr = '<li>%s</li>\n'
+                else:
+                    templstr = '&#160;%s\n'
+                for field, err in errors:
+                    if field is None:
+                        errormsg += templstr % err
+                    else:
+                        errormsg += templstr % '%s: %s' % (self.req._(field), err)
+                if len(errors) > 1:
+                    errormsg = '<ul>%s</ul>' % errormsg
+            return u'<div class="errorMessage">%s</div>' % errormsg
+        return u''
+
+
+###############################################################################
+
+>>>>>>> /tmp/form.py~other.xdns1y
 class metafieldsform(type):
     """metaclass for FieldsForm to retrieve fields defined as class attributes
     and put them into a single ordered list: '_fields_'.
@@ -65,6 +222,7 @@
     __registry__ = 'forms'
 
     parent_form = None
+    force_session_key = None
 
     def __init__(self, req, rset, **kwargs):
         super(Form, self).__init__(req, rset=rset, **kwargs)
@@ -77,6 +235,18 @@
             return self
         return self.parent_form.root_form
 
+    @property
+    def form_previous_values(self):
+        if self.parent_form is None:
+            return self._form_previous_values
+        return self.parent_form.form_previous_values
+
+    @property
+    def form_valerror(self):
+        if self.parent_form is None:
+            return self._form_valerror
+        return self.parent_form.form_valerror
+
     @iclassmethod
     def _fieldsattr(cls_or_self):
         if isinstance(cls_or_self, type):
@@ -127,7 +297,9 @@
         """return the key that may be used to store / retreive data about a
         previous post which failed because of a validation error
         """
-        return '%s#%s' % (self._cw.url(), self.domid)
+        if self.force_session_key is None:
+            return '%s#%s' % (self.req.url(), self.domid)
+        return self.force_session_key
 
     def restore_previous_post(self, sessionkey):
         # get validation session data which may have been previously set.
@@ -136,9 +308,9 @@
         # method on successful commit
         forminfo = self._cw.get_session_data(sessionkey, pop=True)
         if forminfo:
-            # XXX remove req.data assigment once cw.web.widget is killed
-            self._cw.data['formvalues'] = self.form_previous_values = forminfo['values']
-            self._cw.data['formerrors'] = self.form_valerror = forminfo['errors']
+            # XXX remove _cw.data assigment once cw.web.widget is killed
+            self._cw.data['formvalues'] = self._form_previous_values = forminfo['values']
+            self._cw.data['formerrors'] = self._form_valerror = forminfo['errors']
             self._cw.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
@@ -150,5 +322,5 @@
             else:
                 self.form_valerror.eid = foreid
         else:
-            self.form_previous_values = {}
-            self.form_valerror = None
+            self._form_previous_values = {}
+            self._form_valerror = None