summaryrefslogtreecommitdiff
path: root/odoo
diff options
context:
space:
mode:
authorsvs-odoo <svs@odoo.com>2020-12-28 15:45:41 +0000
committersvs-odoo <svs@odoo.com>2021-01-04 09:59:50 +0000
commitcf2b0a505c117a50a91fa022bc1d6bf1eb6d9f77 (patch)
treeb0b7f0fa2798fb2006c3cafc3dc1ab5261e5fc45 /odoo
parent1b10d4e9240a1d4892143284e806ba8ab8281c9d (diff)
[FIX] core: avoid duplicate onchanges
When performing the onchange for the first time on a new record, if a field has a default value, it could be two times in the `todo` field list to compute. closes odoo/odoo#63983 Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Diffstat (limited to 'odoo')
-rw-r--r--odoo/addons/test_new_api/models/test_new_api.py5
-rw-r--r--odoo/addons/test_new_api/tests/test_onchange.py8
-rw-r--r--odoo/models.py3
3 files changed, 15 insertions, 1 deletions
diff --git a/odoo/addons/test_new_api/models/test_new_api.py b/odoo/addons/test_new_api/models/test_new_api.py
index bfe9b2fcee9..0f40589636c 100644
--- a/odoo/addons/test_new_api/models/test_new_api.py
+++ b/odoo/addons/test_new_api/models/test_new_api.py
@@ -553,6 +553,7 @@ class ComputeOnchange(models.Model):
foo = fields.Char()
bar = fields.Char(compute='_compute_bar', store=True)
baz = fields.Char(compute='_compute_baz', store=True, readonly=False)
+ count = fields.Integer(default=0)
line_ids = fields.One2many(
'test_new_api.compute.onchange.line', 'record_id',
compute='_compute_line_ids', store=True, readonly=False
@@ -562,6 +563,10 @@ class ComputeOnchange(models.Model):
compute='_compute_tag_ids', store=True, readonly=False,
)
+ @api.onchange('foo')
+ def _onchange_foo(self):
+ self.count += 1
+
@api.depends('foo')
def _compute_bar(self):
for record in self:
diff --git a/odoo/addons/test_new_api/tests/test_onchange.py b/odoo/addons/test_new_api/tests/test_onchange.py
index a56348cf050..b5cd861edb8 100644
--- a/odoo/addons/test_new_api/tests/test_onchange.py
+++ b/odoo/addons/test_new_api/tests/test_onchange.py
@@ -742,6 +742,14 @@ class TestComputeOnchange(common.TransactionCase):
self.assertEqual(form.bar, "foo6r")
self.assertEqual(form.baz, "baz5")
+ def test_onchange_once(self):
+ """ Modifies `foo` field which will trigger an onchange method and
+ checks it was triggered only one time. """
+ form = Form(self.env['test_new_api.compute.onchange'].with_context(default_foo="oof"))
+ record = form.save()
+ self.assertEqual(record.foo, "oof")
+ self.assertEqual(record.count, 1, "value onchange must be called only one time")
+
def test_onchange_one2many(self):
record = self.env['test_new_api.model_parent_m2o'].create({
'name': 'Family',
diff --git a/odoo/models.py b/odoo/models.py
index 9657e52a20a..9339c731cbd 100644
--- a/odoo/models.py
+++ b/odoo/models.py
@@ -62,6 +62,7 @@ from .tools.misc import CountingStream, clean_context, DEFAULT_SERVER_DATETIME_F
from .tools.translate import _
from .tools import date_utils
from .tools import populate
+from .tools import unique
from .tools.lru import LRU
_logger = logging.getLogger(__name__)
@@ -6205,7 +6206,7 @@ Fields:
# call, 'names' only contains fields with a default. If 'self' is a new
# line in a one2many field, 'names' also contains the one2many's inverse
# field, and that field may not be in nametree.
- todo = list(names) + list(nametree) if first_call else list(names)
+ todo = list(unique(itertools.chain(names, nametree))) if first_call else list(names)
done = set()
# dummy assignment: trigger invalidations on the record