[IMP] core: add force_save support to server-side form

Cf 3b3f6f04af for basic feature
description.

Task 1931580

closes odoo/odoo#30428
This commit is contained in:
Xavier Morel
2019-01-22 11:12:39 +00:00
parent 23e0d2cc17
commit a313f342d3
4 changed files with 36 additions and 4 deletions
@@ -101,6 +101,8 @@
<field name="f2" attrs="{'readonly': [['f1', '=', 63], ['f3', '=', 5]]}"/>
<field name="f3"/>
<field name="f4"/>
<field name="f5" readonly="1"/>
<field name="f6" readonly="1" force_save="1"/>
</form>
</field>
</record>
@@ -10,10 +10,14 @@ class A(models.Model):
f2 = fields.Integer(default=42)
f3 = fields.Integer()
f4 = fields.Integer(compute='_compute_f4')
f5 = fields.Integer()
f6 = fields.Integer()
@api.onchange('f2')
def _on_change_f2(self):
self.f3 = int(self.f2 / 2)
self.f5 = self.f2
self.f6 = self.f2
@api.depends('f1', 'f2')
def _compute_f4(self):
@@ -65,6 +65,19 @@ class TestBasic(TransactionCase):
with self.assertRaises(AssertionError):
f.f2 = 42
def test_readonly_save(self):
""" Should not save readonly fields unless they're force_save
"""
f = Form(self.env['test_testing_utilities.a'], view='test_testing_utilities.non_normalized_attrs')
f.f1 = 1
f.f2 = 987
self.assertEqual(f.f5, 987)
self.assertEqual(f.f6, 987)
r = f.save()
self.assertEqual(r.f5, 0)
self.assertEqual(r.f6, 987)
def test_attrs(self):
""" Checks that attrs/modifiers with non-normalized domains work
"""
+17 -4
View File
@@ -1098,7 +1098,7 @@ class Form(object):
else:
view_id = view or False
fvg = recordp.fields_view_get(view_id, 'form')
arch = etree.fromstring(fvg['arch'])
fvg['tree'] = etree.fromstring(fvg['arch'])
object.__setattr__(self, '_view', fvg)
# TODO: make this less crappy?
@@ -1107,7 +1107,7 @@ class Form(object):
if descr['type'] != 'one2many':
continue
node = next(n for n in arch.iter('field') if n.get('name') == f)
node = self._get_node(f)
default_view = next(
(m for m in node.get('mode', 'tree').split(',') if m != 'form'),
'tree'
@@ -1130,10 +1130,12 @@ class Form(object):
# if the default view is a kanban or a non-editable list, the
# "edition controller" is the form view
edition = views['form']
edition['tree'] = etree.fromstring(edition['arch'])
if default_view == 'tree':
subarch = etree.fromstring(views['tree']['arch'])
if subarch.get('editable'):
edition = views['tree']
edition['tree'] = subarch
self._process_fvg(submodel, edition)
descr['views']['edition'] = edition
@@ -1153,6 +1155,14 @@ class Form(object):
else:
self._init_from_defaults(self._model)
def _get_node(self, f):
""" Find etree node for the field ``f`` in the current arch
"""
return next(
n for n in self._view['tree'].iter('field')
if n.get('name') == f
)
def __str__(self):
return "<%s %s(%s)>" % (
type(self).__name__,
@@ -1171,7 +1181,7 @@ class Form(object):
# pre-resolve modifiers & bind to arch toplevel
modifiers = fvg['modifiers'] = {}
contexts = fvg['contexts'] = {}
for f in etree.fromstring(fvg['arch']).iter('field'):
for f in fvg['tree'].iter('field'):
fname = f.get('name')
modifiers[fname] = {
modifier: domain if isinstance(domain, bool) else normalize_domain(domain)
@@ -1356,8 +1366,11 @@ class Form(object):
# skip unmodified fields
if f not in self._changed:
continue
if self._get_modifier(f, 'readonly'):
continue
node = self._get_node(f)
if not node.get('force_save'):
continue
# TODO: filter out (1, _, {}) from o2m values
values[f] = v
return values