[FIX] core: missing default values with inherits
Consider some model A that "_inherits" from model B, which itself "_inherits" from model C. Also consider a field F on model C, which is inherited by both models B and A. Now create a record from model A, with a given record for model C, no record for model B, and a default value for field F. This should create a record in A, connected to a new record in B, connected to the given record in C, and the default value should be ignored, as a record from C is given. Before this commit, the given record in C is modified with the default value for F. The default value is considered because no record is given for B, and that value is used to modify the given record in C. The fix consists in discarding default values by considering potential ancestor records when parent records are not given. closes odoo/odoo#61165 X-original-commit: b83dfaa2c9bcc6bc7f8df19ed0e442554816709b Signed-off-by: Raphael Collet (rco) <rco@openerp.com> Co-authored-by: Raphael Collet <rco@odoo.com>
This commit is contained in:
committed by
Raphael Collet
co-authored by
Raphael Collet
parent
51ed48b1b6
commit
55bd019a62
@@ -13,6 +13,7 @@ class Unit(models.Model):
|
||||
surname = fields.Char(compute='_compute_surname')
|
||||
line_ids = fields.One2many('test.unit.line', 'unit_id')
|
||||
readonly_name = fields.Char('Readonly Name', readonly=True)
|
||||
size = fields.Integer()
|
||||
|
||||
@api.depends('name')
|
||||
def _compute_surname(self):
|
||||
@@ -38,6 +39,7 @@ class Box(models.Model):
|
||||
unit_id = fields.Many2one('test.unit', 'Unit', required=True,
|
||||
ondelete='cascade')
|
||||
field_in_box = fields.Char('Field1')
|
||||
size = fields.Integer()
|
||||
|
||||
|
||||
# We add a third level of _inherits
|
||||
|
||||
@@ -17,6 +17,24 @@ class test_inherits(common.TransactionCase):
|
||||
self.assertEqual(pallet.field_in_box, 'box')
|
||||
self.assertEqual(pallet.field_in_pallet, 'pallet')
|
||||
|
||||
def test_create_3_levels_inherits_with_defaults(self):
|
||||
unit = self.env['test.unit'].create({
|
||||
'name': 'U',
|
||||
'state': 'a',
|
||||
'size': 1,
|
||||
})
|
||||
ctx = {
|
||||
'default_state': 'b', # 'state' is inherited from 'test.unit'
|
||||
'default_size': 2, # 'size' is inherited from 'test.box'
|
||||
}
|
||||
pallet = self.env['test.pallet'].with_context(ctx).create({
|
||||
'name': 'P',
|
||||
'unit_id': unit.id, # grand-parent field is set
|
||||
})
|
||||
# default 'state' should be ignored, but default 'size' should not
|
||||
self.assertEqual(pallet.state, 'a')
|
||||
self.assertEqual(pallet.size, 2)
|
||||
|
||||
def test_read_3_levels_inherits(self):
|
||||
""" Check that we can read an inherited field on 3 levels """
|
||||
pallet = self.env.ref('test_inherits.pallet_a')
|
||||
|
||||
+21
-6
@@ -1807,18 +1807,33 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
|
||||
@api.model
|
||||
def _add_missing_default_values(self, values):
|
||||
# avoid overriding inherited values when parent is set
|
||||
avoid_models = {
|
||||
parent_model
|
||||
for parent_model, parent_field in self._inherits.items()
|
||||
if parent_field in values
|
||||
}
|
||||
avoid_models = set()
|
||||
|
||||
def collect_models_to_avoid(model):
|
||||
for parent_mname, parent_fname in model._inherits.items():
|
||||
if parent_fname in values:
|
||||
avoid_models.add(parent_mname)
|
||||
else:
|
||||
# manage the case where an ancestor parent field is set
|
||||
collect_models_to_avoid(self.env[parent_mname])
|
||||
|
||||
collect_models_to_avoid(self)
|
||||
|
||||
def avoid(field):
|
||||
# check whether the field is inherited from one of avoid_models
|
||||
if avoid_models:
|
||||
while field.inherited:
|
||||
field = field.related_field
|
||||
if field.model_name in avoid_models:
|
||||
return True
|
||||
return False
|
||||
|
||||
# compute missing fields
|
||||
missing_defaults = {
|
||||
name
|
||||
for name, field in self._fields.items()
|
||||
if name not in values
|
||||
if not (field.inherited and field.related_field.model_name in avoid_models)
|
||||
if not avoid(field)
|
||||
}
|
||||
|
||||
if not missing_defaults:
|
||||
|
||||
Reference in New Issue
Block a user