[forms] Do not raise errors on composite required relation being deleted
authorFlorent Cayré <florent.cayre@logilab.fr>
Mon, 14 Dec 2015 14:29:22 +0100
changeset 11065 c7dbd10648e6
parent 11064 113e9da47afc
child 11066 dcbb64d3a1d9
[forms] Do not raise errors on composite required relation being deleted The entity included in the composite will be deleted in such a case, so the field is not required even when the cardinality is '1' or '+'. Related to #8529868
web/formfields.py
web/test/data/schema.py
web/test/unittest_application.py
--- a/web/formfields.py	Mon Dec 07 11:58:17 2015 +0100
+++ b/web/formfields.py	Mon Dec 14 14:29:22 2015 +0100
@@ -76,7 +76,7 @@
 from yams.constraints import (SizeConstraint, StaticVocabularyConstraint,
                               FormatConstraint)
 
-from cubicweb import Binary, tags, uilib
+from cubicweb import Binary, tags, uilib, neg_role
 from cubicweb.utils import support_args
 from cubicweb.web import INTERNAL_FIELD_VALUE, ProcessFormError, eid_param, \
      formwidgets as fw
@@ -1195,10 +1195,13 @@
     else:
         targetschema = rdef.subject
     card = rdef.role_cardinality(role)
+    composite = getattr(rdef, 'composite', None)
     kwargs['name'] = rschema.type
     kwargs['role'] = role
     kwargs['eidparam'] = True
-    kwargs.setdefault('required', card in '1+')
+    # don't mark composite relation as required, we want the composite element
+    # to be removed when not linked to its parent
+    kwargs.setdefault('required', card in '1+' and composite != neg_role(role))
     if role == 'object':
         kwargs.setdefault('label', (eschema.type, rschema.type + '_object'))
     else:
--- a/web/test/data/schema.py	Mon Dec 07 11:58:17 2015 +0100
+++ b/web/test/data/schema.py	Mon Dec 14 14:29:22 2015 +0100
@@ -96,6 +96,9 @@
 class Filesystem(EntityType):
     name = String()
 
+class DirectoryPermission(EntityType):
+    value = String()
+
 class parent_fs(RelationDefinition):
     name = 'parent'
     subject = 'Directory'
@@ -103,6 +106,8 @@
 
 class Directory(EntityType):
     name = String(required=True)
+    has_permission = SubjectRelation('DirectoryPermission', cardinality='*1',
+                                     composite='subject')
 
 class parent_directory(RelationDefinition):
     name = 'parent'
--- a/web/test/unittest_application.py	Mon Dec 07 11:58:17 2015 +0100
+++ b/web/test/unittest_application.py	Mon Dec 14 14:29:22 2015 +0100
@@ -451,6 +451,29 @@
             self.assertFalse(cnx.find('Directory', eid=subd.eid))
             self.assertTrue(cnx.find('Filesystem', eid=fs.eid))
 
+    def test_delete_mandatory_composite(self):
+        with self.admin_access.repo_cnx() as cnx:
+            perm = cnx.create_entity('DirectoryPermission')
+            mydir = cnx.create_entity('Directory', name=u'dir',
+                                      has_permission=perm)
+            cnx.commit()
+
+        with self.admin_access.web_request() as req:
+            dir_eid = unicode(mydir.eid)
+            perm_eid = unicode(perm.eid)
+            req.form = {
+                'eid': [dir_eid, perm_eid],
+                '__maineid' : dir_eid,
+                '__type:%s' % dir_eid: 'Directory',
+                '__type:%s' % perm_eid: 'DirectoryPermission',
+                '_cw_entity_fields:%s' % dir_eid: '',
+                '_cw_entity_fields:%s' % perm_eid: 'has_permission-object',
+                'has_permission-object:%s' % perm_eid: '',
+                }
+            path, _params = self.expect_redirect_handle_request(req, 'edit')
+            self.assertTrue(req.find('Directory', eid=mydir.eid))
+            self.assertFalse(req.find('DirectoryPermission', eid=perm.eid))
+
     def test_ajax_view_raise_arbitrary_error(self):
         class ErrorAjaxView(view.View):
             __regid__ = 'test.ajax.error'