[autoform] Go through guess_field even when field class is specified using uicfg
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 20 Jan 2017 10:31:04 +0100
changeset 11910 af969080e7e6
parent 11900 8496135b6dc1
child 11911 37726f66ff82
[autoform] Go through guess_field even when field class is specified using uicfg guess_field does not only find the proper field class for some attribute/relation, but also do some basic configuration depending on e.g. constraints. Before this patch, if one was specifying explicitly the field class using uicfg.autoform_field, this automatic configuration wasn't happening. Change form.field_by_name and ff.guess_field so explicit class are also automatically configured now. Closes #14474840
cubicweb/web/formfields.py
cubicweb/web/test/unittest_views_forms.py
cubicweb/web/views/forms.py
--- a/cubicweb/web/formfields.py	Thu Jan 19 14:53:05 2017 +0100
+++ b/cubicweb/web/formfields.py	Fri Jan 20 10:31:04 2017 +0100
@@ -1235,8 +1235,19 @@
         kwargs.setdefault('label', (eschema.type, rschema.type))
     kwargs.setdefault('help', rdef.description)
     if rschema.final:
-        fieldclass = FIELDS[targetschema]
-        if fieldclass is StringField:
+        fieldclass = kwargs.pop('fieldclass', FIELDS[targetschema])
+        if issubclass(fieldclass, FileField):
+            if req:
+                aff_kwargs = req.vreg['uicfg'].select('autoform_field_kwargs', req)
+            else:
+                aff_kwargs = _AFF_KWARGS
+            for metadata in KNOWN_METAATTRIBUTES:
+                metaschema = eschema.has_metadata(rschema, metadata)
+                if metaschema is not None:
+                    metakwargs = aff_kwargs.etype_get(eschema, metaschema, 'subject')
+                    kwargs['%s_field' % metadata] = guess_field(eschema, metaschema,
+                                                                req=req, **metakwargs)
+        elif issubclass(fieldclass, StringField):
             if eschema.has_metadata(rschema, 'format'):
                 # use RichTextField instead of StringField if the attribute has
                 # a "format" metadata. But getting information from constraints
@@ -1253,18 +1264,6 @@
             for cstr in rdef.constraints:
                 if isinstance(cstr, SizeConstraint) and cstr.max is not None:
                     kwargs['max_length'] = cstr.max
-            return StringField(**kwargs)
-        if fieldclass is FileField:
-            if req:
-                aff_kwargs = req.vreg['uicfg'].select('autoform_field_kwargs', req)
-            else:
-                aff_kwargs = _AFF_KWARGS
-            for metadata in KNOWN_METAATTRIBUTES:
-                metaschema = eschema.has_metadata(rschema, metadata)
-                if metaschema is not None:
-                    metakwargs = aff_kwargs.etype_get(eschema, metaschema, 'subject')
-                    kwargs['%s_field' % metadata] = guess_field(eschema, metaschema,
-                                                                req=req, **metakwargs)
         return fieldclass(**kwargs)
     return RelationField.fromcardinality(card, **kwargs)
 
--- a/cubicweb/web/test/unittest_views_forms.py	Thu Jan 19 14:53:05 2017 +0100
+++ b/cubicweb/web/test/unittest_views_forms.py	Fri Jan 20 10:31:04 2017 +0100
@@ -20,6 +20,8 @@
 
 from cubicweb.devtools.testlib import CubicWebTC
 from cubicweb.web.views.autoform import InlinedFormField
+from cubicweb.web.views.forms import EntityFieldsForm
+
 
 class InlinedFormTC(CubicWebTC):
 
@@ -68,6 +70,20 @@
                                                   InlinedFormField(view=formview)])
                 self.assertTrue(formview._get_removejs())
 
+    def test_field_by_name_consider_aff(self):
+        class MyField(object):
+            def __init__(self, *args, **kwargs):
+                pass
+
+        EntityFieldsForm.uicfg_aff.tag_attribute(('CWUser', 'firstname'), MyField)
+        try:
+            with self.admin_access.web_request() as req:
+                form = req.vreg['forms'].select('base', req, entity=req.user)
+                self.assertIsInstance(form.field_by_name('firstname', 'subject', req.user.e_schema),
+                                      MyField)
+        finally:
+            EntityFieldsForm.uicfg_aff.del_rtag('CWUser', 'firstname', '*', 'subject')
+
 
 if __name__ == '__main__':
     import unittest
--- a/cubicweb/web/views/forms.py	Thu Jan 19 14:53:05 2017 +0100
+++ b/cubicweb/web/views/forms.py	Fri Jan 20 10:31:04 2017 +0100
@@ -318,16 +318,16 @@
             rschema = eschema.schema.rschema(name)
             # XXX use a sample target type. Document this.
             tschemas = rschema.targets(eschema, role)
-            fieldcls = cls_or_self.uicfg_aff.etype_get(
+            fieldclass = cls_or_self.uicfg_aff.etype_get(
                 eschema, rschema, role, tschemas[0])
             kwargs = cls_or_self.uicfg_affk.etype_get(
                 eschema, rschema, role, tschemas[0])
             if kwargs is None:
                 kwargs = {}
-            if fieldcls:
-                if not isinstance(fieldcls, type):
-                    return fieldcls  # already and instance
-                return fieldcls(name=name, role=role, eidparam=True, **kwargs)
+            if fieldclass:
+                if not isinstance(fieldclass, type):
+                    return fieldclass  # already an instance
+                kwargs['fieldclass'] = fieldclass
             if isinstance(cls_or_self, type):
                 req = None
             else: