From f4a7c8d395afa0f2087c92d5406ffdc04480eedc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 16 Nov 2019 15:49:50 +0100 Subject: [PATCH] Do not try to save reverse field of One2Many Even if the record is already created, the _save_values should not process the reverse field otherwise it creates an infinite loop. issue8742 --- trytond/model/modelstorage.py | 33 ++++++++++++++++++---------- trytond/tests/test_field_one2many.py | 25 +++++++++++++++++++++ 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/trytond/model/modelstorage.py b/trytond/model/modelstorage.py index 713e1872e7..df6704aa84 100644 --- a/trytond/model/modelstorage.py +++ b/trytond/model/modelstorage.py @@ -1613,20 +1613,29 @@ class ModelStorage(Model): to_create = [] to_write = [] for target in targets: - if target.id is None or target.id < 0: - if field._type == 'one2many' and field.field: - # Don't store old target link - setattr(target, field.field, None) - to_create.append(target._save_values) + if (field._type == 'one2many' + and field.field + and target._values): + t_values = target._values.copy() + # Don't look at reverse field + target._values.pop(field.field, None) else: - if target.id in to_remove: - to_remove.remove(target.id) + t_values = None + try: + if target.id is None or target.id < 0: + to_create.append(target._save_values) else: - to_add.append(target.id) - target_values = target._save_values - if target_values: - to_write.append( - ('write', [target.id], target_values)) + if target.id in to_remove: + to_remove.remove(target.id) + else: + to_add.append(target.id) + target_values = target._save_values + if target_values: + to_write.append( + ('write', [target.id], target_values)) + finally: + if t_values: + target._values = t_values value = [] if to_remove: value.append(('remove', to_remove)) diff --git a/trytond/tests/test_field_one2many.py b/trytond/tests/test_field_one2many.py index 6f799431d4..9366b0c825 100644 --- a/trytond/tests/test_field_one2many.py +++ b/trytond/tests/test_field_one2many.py @@ -22,6 +22,31 @@ class CommonTestCaseMixin: self.assertEqual(target.origin, record) + @with_transaction() + def test_save_reverse_field(self): + "Test save with reverse field set" + One2Many = self.One2Many() + Target = self.One2ManyTarget() + + record = One2Many() + target = Target() + record.targets = [target] + + record.save() + + @with_transaction() + def test_save_reverse_field_saved(self): + "Test save with reverse field set on saved" + One2Many = self.One2Many() + Target = self.One2ManyTarget() + + record = One2Many() + target = Target() + target.save() + record.targets = [target] + + record.save() + @with_transaction() def test_set_reverse_field_dict(self): "Test reverse field is set on dict"