diff -r 92ead039d3d0 -r 94cc7cad3d2d web/form.py --- 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 + and 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 = '
  • %s
  • \n' + else: + templstr = ' %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 = '' % errormsg + return u'
    %s
    ' % 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