[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
--- 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: