new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore) tls-sprint
authorsylvain.thenault@logilab.fr
Thu, 09 Apr 2009 14:31:32 +0200
branchtls-sprint
changeset 1318 50e1a778c5ee
parent 1317 12dc957a5b55
child 1319 2fe3df4e1e60
new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
web/form.py
web/views/baseforms.py
web/views/editforms.py
web/views/editviews.py
web/views/eproperties.py
web/views/massmailing.py
web/views/workflow.py
--- a/web/form.py	Thu Apr 09 13:59:44 2009 +0200
+++ b/web/form.py	Thu Apr 09 14:31:32 2009 +0200
@@ -23,25 +23,15 @@
 from cubicweb.web.formrenderers import FormRenderer
 from cubicweb.web import formwidgets as fwdgs
 
-
-
-# XXX should disappear 
-class FormMixIn(object):
-    """abstract form mix-in
-    XXX: you should inherit from this FIRST (obscure pb with super call)"""
+class FormViewMixIn(object):
+    """abstract form view mix-in"""
     category = 'form'
     controller = 'edit'
-    domid = 'entityForm'
-    
     http_cache_manager = NoHTTPCacheManager
     add_to_breadcrumbs = False
-    skip_relations = set()
     
     def __init__(self, req, rset, **kwargs):
-        super(FormMixIn, self).__init__(req, rset, **kwargs)
-        self.maxrelitems = self.req.property_value('navigation.related-limit')
-        self.maxcomboitems = self.req.property_value('navigation.combobox-limit')
-        self.force_display = not not req.form.get('__force_display')
+        super(FormViewMixIn, self).__init__(req, rset, **kwargs)
         # 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
@@ -76,12 +66,13 @@
         """
         return False
 
-    @property
-    def limit(self):
-        if self.force_display:
-            return None
-        return self.maxrelitems + 1
-    
+
+# XXX should disappear 
+class FormMixIn(object):
+    """abstract form mix-in
+    XXX: you should inherit from this FIRST (obscure pb with super call)
+    """
+
     def initialize_varmaker(self):
         varmaker = self.req.get_page_data('rql_varmaker')
         if varmaker is None:
@@ -89,6 +80,51 @@
             self.req.set_page_data('rql_varmaker', varmaker)
         self.varmaker = varmaker
 
+    # XXX deprecated with new form system. Should disappear
+    
+    domid = 'entityForm'
+    category = 'form'
+    controller = 'edit'
+    http_cache_manager = NoHTTPCacheManager
+    add_to_breadcrumbs = False
+    
+    def __init__(self, req, rset, **kwargs):
+        super(FormMixIn, self).__init__(req, rset, **kwargs)
+        # 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
+        formurl = req.url()
+        forminfo = req.get_session_data(formurl)
+        if forminfo:
+            req.data['formvalues'] = forminfo['values']
+            req.data['formerrors'] = errex = forminfo['errors']
+            req.data['displayederrors'] = set()
+            # if some validation error occured on entity creation, we have to
+            # get the original variable name from its attributed eid
+            foreid = errex.entity
+            for var, eid in forminfo['eidmap'].items():
+                if foreid == eid:
+                    errex.eid = var
+                    break
+            else:
+                errex.eid = foreid    
+        
+    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()
@@ -122,8 +158,6 @@
         label = self.req._(label or stdmsgs.BUTTON_CANCEL).capitalize()
         return self.button(label, type=type, **kwargs)
 
-    # XXX deprecated with new form system
-
     def need_multipart(self, entity, categories=('primary', 'secondary')):
         """return a boolean indicating if form's enctype should be multipart
         """
--- a/web/views/baseforms.py	Thu Apr 09 13:59:44 2009 +0200
+++ b/web/views/baseforms.py	Thu Apr 09 14:31:32 2009 +0200
@@ -40,7 +40,7 @@
 
     title = _('edition')
     controller = 'edit'
-    skip_relations = FormMixIn.skip_relations.copy()
+    skip_relations = set()
     
     EDITION_BODY = u'''\
  %(errormsg)s
--- a/web/views/editforms.py	Thu Apr 09 13:59:44 2009 +0200
+++ b/web/views/editforms.py	Thu Apr 09 14:31:32 2009 +0200
@@ -22,7 +22,7 @@
 from cubicweb.common import tags
 from cubicweb.web import INTERNAL_FIELD_VALUE, stdmsgs, uicfg
 from cubicweb.web.form import (FieldNotFound, CompositeForm, EntityFieldsForm,
-                               FormMixIn)
+                               FormViewMixIn)
 from cubicweb.web.formfields import guess_field
 from cubicweb.web.formwidgets import Button, SubmitButton, ResetButton
 from cubicweb.web.formrenderers import (FormRenderer, EntityFormRenderer,
@@ -44,7 +44,7 @@
     return u'[<a class="handle" href="%s" id="handle%s">%s</a>]' % (js, nodeid, label)
 
 
-class DeleteConfForm(EntityView):
+class DeleteConfForm(FormViewMixIn, EntityView):
     """form used to confirm deletion of some entities"""
     id = 'deleteconf'
     title = _('delete')
@@ -79,7 +79,7 @@
         w(form.form_render())
 
 
-class ClickAndEditForm(FormMixIn, EntityView):
+class ClickAndEditFormView(FormViewMixIn, EntityView):
     """form used to permit ajax edition of an attribute of an entity in a view
     
     (double-click on the field to see an appropriate edition widget)
@@ -297,6 +297,14 @@
                                     eidparam=True)
             if field is not None:
                 self.fields.append(field)
+        self.maxrelitems = self.req.property_value('navigation.related-limit')
+        self.force_display = not not req.form.get('__force_display')
+        
+    @property
+    def related_limit(self):
+        if self.force_display:
+            return None
+        return self.maxrelitems + 1
     
     def relations_by_category(self, categories=None, permission=None):
         """return a list of (relation schema, target schemas, role) matching
@@ -353,7 +361,7 @@
         entity = self.edited_entity
         pending_deletes = self.req.get_pending_deletes(entity.eid)
         for label, rschema, role in self.srelations_by_category('generic', 'add'):
-            relatedrset = entity.related(rschema, role, limit=self.limit)
+            relatedrset = entity.related(rschema, role, limit=self.related_limit)
             if rschema.has_perm(self.req, 'delete'):
                 toggable_rel_link_func = toggable_relation_link
             else:
@@ -422,7 +430,7 @@
         return not existant or card in '+*'
 
     
-class EditionFormView(EntityView):
+class EditionFormView(FormViewMixIn, EntityView):
     """display primary entity edition form"""    
     id = 'edition'
     # add yes() so it takes precedence over deprecated views in baseforms,
@@ -430,7 +438,6 @@
     __select__ = one_line_rset() & non_final_entity() & yes()
 
     title = _('edition')
-    controller = 'edit'
     
     def cell_call(self, row, col, **kwargs):
         entity = self.complete_entity(row, col)
@@ -555,7 +562,7 @@
             self.form_add_subform(form)
 
         
-class TableEditFormView(EntityView):
+class TableEditFormView(FormViewMixIn, EntityView):
     id = 'muledit'
     __select__ = EntityView.__select__ & yes()
     title = _('multiple edit')
@@ -569,7 +576,7 @@
         self.w(form.form_render(renderer=EntityCompositeFormRenderer()))
 
 
-class InlineEntityEditionFormView(EntityView):
+class InlineEntityEditionFormView(FormViewMixIn, EntityView):
     id = 'inline-edition'
     __select__ = non_final_entity() & match_kwargs('peid', 'rtype')
     removejs = "removeInlinedEntity('%s', '%s', '%s')"
--- a/web/views/editviews.py	Thu Apr 09 13:59:44 2009 +0200
+++ b/web/views/editviews.py	Thu Apr 09 14:31:32 2009 +0200
@@ -76,12 +76,6 @@
     id = 'unrelateddivs'
     __select__ = match_form_params('relation')
 
-    @property
-    def limit(self):
-        if self.req.form.get('__force_display'):
-            return None
-        return self.req.property_value('navigation.related-limit') + 1
-
     def cell_call(self, row, col):
         entity = self.entity(row, col)
         relname, target = self.req.form.get('relation').rsplit('_', 1)
@@ -128,7 +122,8 @@
         form = self.vreg.select_object('forms', 'edition', self.req,
                                        entity=entity)
         field = form.field_by_name(rschema, target, entity.__class__)
-        for eview, reid in form.form_field_vocabulary(field, self.limit):
+        limit = self.req.property_value('navigation.combobox-limit')
+        for eview, reid in form.form_field_vocabulary(field, limit):
             if reid is None:
                 options.append('<option class="separator">-- %s --</option>'
                                % html_escape(eview))
--- a/web/views/eproperties.py	Thu Apr 09 13:59:44 2009 +0200
+++ b/web/views/eproperties.py	Thu Apr 09 14:31:32 2009 +0200
@@ -15,10 +15,10 @@
                                 match_user_groups, entity_implements)
 from cubicweb.utils import UStringIO
 from cubicweb.view import StartupView
-from cubicweb.web import INTERNAL_FIELD_VALUE, eid_param
+from cubicweb.web import INTERNAL_FIELD_VALUE, eid_param, uicfg
 from cubicweb.web.views import baseviews
 from cubicweb.web import stdmsgs
-from cubicweb.web.form import FormMixIn, CompositeForm, EntityFieldsForm
+from cubicweb.web.form import CompositeForm, EntityFieldsForm, FormViewMixIn
 from cubicweb.web.formfields import FIELDS, StringField
 from cubicweb.web.formwidgets import Select, Button, SubmitButton
 from cubicweb.web.views.editforms import AutomaticEntityForm
@@ -50,12 +50,11 @@
     skip_none = False
 
 
-class SystemEPropertiesForm(FormMixIn, StartupView):
+class SystemEPropertiesForm(FormViewMixIn, StartupView):
     id = 'systemepropertiesform'
     __select__ = none_rset() & match_user_groups('managers')
 
     title = _('site configuration')
-    controller = 'edit'
     category = 'startupview'
 
     def linkable(self):
@@ -83,7 +82,7 @@
 
     def call(self, **kwargs):
         """The default view representing the application's index"""
-        self.req.add_js(('cubicweb.edition.js', 'cubicweb.preferences.js'))
+        self.req.add_js('cubicweb.preferences.js')
         self.req.add_css('cubicweb.preferences.css')
         vreg = self.vreg
         values = self.defined_keys
@@ -325,7 +324,6 @@
                 wdg.attrs.setdefault('size', 3)
         self.widget = wdg
 
-from cubicweb.web import uicfg
 uicfg.rfields.set_rtag(PropertyKeyField, 'pkey', 'subject', 'EProperty')
 uicfg.rfields.set_rtag(PropertyValueField, 'value', 'subject', 'EProperty')
     
--- a/web/views/massmailing.py	Thu Apr 09 13:59:44 2009 +0200
+++ b/web/views/massmailing.py	Thu Apr 09 14:31:32 2009 +0200
@@ -13,7 +13,7 @@
 from cubicweb.view import EntityView
 from cubicweb.web import stdmsgs
 from cubicweb.web.action import Action
-from cubicweb.web.form import FieldsForm, FormRenderer
+from cubicweb.web.form import FieldsForm, FormRenderer, FormViewMixIn
 from cubicweb.web.formfields import StringField
 from cubicweb.web.formwidgets import CheckBox, TextInput, AjaxWidget, ImgButton
 
@@ -100,7 +100,7 @@
         w(u'</table>')
 
     
-class MassMailingFormView(EntityView):
+class MassMailingFormView(FormViewMixIn, EntityView):
     id = 'massmailing'
     __select__ = implements(IEmailable) & match_user_groups('managers', 'users')
 
--- a/web/views/workflow.py	Thu Apr 09 13:59:44 2009 +0200
+++ b/web/views/workflow.py	Thu Apr 09 14:31:32 2009 +0200
@@ -17,6 +17,7 @@
                                 relation_possible, match_form_params)
 from cubicweb.interfaces import IWorkflowable
 from cubicweb.web import stdmsgs, action, component, form
+from cubicweb.web.form import FormViewMixIn
 from cubicweb.web.formfields import StringField,  RichTextField
 from cubicweb.web.formwidgets import HiddenInput, SubmitButton, Button
 from cubicweb.web.views import TmpFileViewMixin
@@ -42,7 +43,7 @@
                      Button(stdmsgs.NO, cwaction='cancel')]
 
         
-class ChangeStateFormView(view.EntityView):
+class ChangeStateFormView(FormViewMixIn, view.EntityView):
     id = 'statuschange'
     title = _('status change')
     __select__ = implements(IWorkflowable) & match_form_params('treid')