Do not use init values for new record without id to compute the changed values

When using new instance to fill a xxx2Many field, all the values must be
considered as changed and we should not expect any initial value.

Closes #13716
This commit is contained in:
Cédric Krier committed 2024-11-30 12:56:41 +01:00
1 parent 34df4552e5
commit 1360ae6c5d
3 files changed
+42 -19

No files matched your search

+4 -4
View File
@@ -284,6 +284,8 @@ class Model(URLMixin, PoolBase, metaclass=ModelMeta):
id = int(id)
self._id = id
self._deleted = self._removed = None
self._values = None
self._init_values = None
if kwargs:
self._values = self._record()
parent_values = defaultdict(dict)
@@ -305,10 +307,8 @@ class Model(URLMixin, PoolBase, metaclass=ModelMeta):
# to ensure it was evaluated with all the fields
for name, value in has_context.items():
setattr(self, name, value)
self._init_values = self._values._copy()
else:
self._values = None
self._init_values = None
if id is not None:
self._init_values = self._values._copy()
def __copy__(self):
copied = self.__class__(self.id)
+4 -9
View File
@@ -870,7 +870,9 @@ class ModelView(Model):
value = value.id
elif field._type in ['one2many', 'many2many']:
targets = value
if fname in init_values:
if self.id is None:
init_targets = []
elif fname in init_values:
init_targets = init_values._get(fname)
elif isinstance(field, fields.Function):
init_targets = []
@@ -898,14 +900,7 @@ class ModelView(Model):
value['update'].append(target_changed)
else:
if isinstance(target, ModelView):
# Ensure initial values are returned because
# target was instantiated on server side.
target_init_values = target._init_values
target._init_values = None
try:
added_values = target._changed_values()
finally:
target._init_values = target_init_values
added_values = target._changed_values()
else:
added_values = target._default_values
added_values['id'] = target.id
+34 -6
View File
@@ -185,7 +185,7 @@ class ModelView(TestCase):
Model = pool.get('test.modelview.changed_values')
Target = pool.get('test.modelview.changed_values.target')
record = Model(targets=[], m2m_targets=[], m2m_function=[])
record = Model(id=-1, targets=[], m2m_targets=[], m2m_function=[])
self.assertEqual(record._changed_values(), {})
@@ -208,7 +208,7 @@ class ModelView(TestCase):
'dictionary': {'key': 'value'},
})
record = Model(name='test', target=1, targets=[
record = Model(id=-1, name='test', target=1, targets=[
{'id': 1, 'name': 'foo'},
{'id': 2},
],
@@ -243,7 +243,7 @@ class ModelView(TestCase):
})
# change only one2many record
record = Model(targets=[{'id': 1, 'name': 'foo'}])
record = Model(id=-1, targets=[{'id': 1, 'name': 'foo'}])
self.assertEqual(record._changed_values(), {})
target, = record.targets
@@ -256,7 +256,7 @@ class ModelView(TestCase):
})
# no initial value
record = Model(targets=[], m2m_targets=[], m2m_function=[])
record = Model(id=-1, targets=[], m2m_targets=[], m2m_function=[])
record._values = record._record()
target = Target(id=1)
record._values['targets'] = [target]
@@ -267,6 +267,34 @@ class ModelView(TestCase):
},
})
@with_transaction()
def test_changed_values_with_no_id(self):
"Test changed values with no id"
pool = Pool()
Model = pool.get('test.modelview.changed_values')
Target = pool.get('test.modelview.changed_values.target')
record = Model(
name='foo',
target=Target(1),
ref_target=Target(2),
targets=[Target(name='bar')],
multiselection=['a'],
dictionary={'key': 'value'})
self.assertEqual(record._changed_values(), {
'name': 'foo',
'target': 1,
'ref_target': 'test.modelview.changed_values.target,2',
'targets': {
'add': [
(0, {'id': None, 'name': 'bar'}),
],
},
'multiselection': ('a',),
'dictionary': {'key': 'value'},
})
@with_transaction()
def test_changed_values_2many_function(self):
"Test changed values for xxx2many function field"
@@ -315,7 +343,7 @@ class ModelView(TestCase):
Target = pool.get('test.modelview.changed_values.target')
target = Target(1)
record = Model(targets=[target])
record = Model(id=-1, targets=[target])
Model.targets.remove(record, [target])
self.assertEqual(record._changed_values(), {
@@ -332,7 +360,7 @@ class ModelView(TestCase):
Target = pool.get('test.modelview.changed_values.target')
target = Target(1)
record = Model(m2m_targets=[target])
record = Model(id=-1, m2m_targets=[target])
Model.m2m_targets.delete(record, [target])
self.assertEqual(record._changed_values(), {