diff options
| author | svs-odoo <svs@odoo.com> | 2020-12-28 15:45:41 +0000 |
|---|---|---|
| committer | svs-odoo <svs@odoo.com> | 2021-01-04 09:59:50 +0000 |
| commit | cf2b0a505c117a50a91fa022bc1d6bf1eb6d9f77 (patch) | |
| tree | b0b7f0fa2798fb2006c3cafc3dc1ab5261e5fc45 | |
| parent | 1b10d4e9240a1d4892143284e806ba8ab8281c9d (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>
| -rw-r--r-- | odoo/addons/test_new_api/models/test_new_api.py | 5 | ||||
| -rw-r--r-- | odoo/addons/test_new_api/tests/test_onchange.py | 8 | ||||
| -rw-r--r-- | odoo/models.py | 3 |
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 |
