From f048652ca7ef761d69a4b1fce2c9db812380b0c0 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Thu, 5 Sep 2019 08:54:51 +0000 Subject: [PATCH] [FIX] models: callable in api.depends() sees valid _rec_name Determine `model._rec_name` before the dependencies of the fields. The compute method of the automatic field `display_name` uses a callable depends that retrieves `model._rec_name`. closes odoo/odoo#36479 Signed-off-by: Raphael Collet (rco) --- .../test_new_api/tests/test_new_fields.py | 7 +++++++ odoo/fields.py | 12 ++++++------ odoo/models.py | 18 +++++++++--------- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/odoo/addons/test_new_api/tests/test_new_fields.py b/odoo/addons/test_new_api/tests/test_new_fields.py index 343e184e5ca..afdb8cf6d92 100644 --- a/odoo/addons/test_new_api/tests/test_new_fields.py +++ b/odoo/addons/test_new_api/tests/test_new_fields.py @@ -74,6 +74,13 @@ class TestFields(common.TransactionCase): field = self.env['test_new_api.message']._fields['x_bool_false_computed'] self.assertFalse(field.depends) + def test_10_display_name(self): + """ test definition of automatic field 'display_name' """ + field = type(self.env['test_new_api.discussion']).display_name + self.assertTrue(field.automatic) + self.assertTrue(field.compute) + self.assertEqual(field.depends, ('name',)) + def test_10_non_stored(self): """ test non-stored fields """ # a field declared with store=False should not have a column diff --git a/odoo/fields.py b/odoo/fields.py index f86bf938d33..a84dfa92e62 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -478,6 +478,10 @@ class Field(MetaField('DummyField', (object,), {})): def _setup_regular_base(self, model): """ Setup the attributes of a non-related field. """ + pass + + def _setup_regular_full(self, model): + """ Determine the dependencies and inverse field(s) of ``self``. """ def make_depends(deps): return tuple(deps(model) if callable(deps) else deps) @@ -489,10 +493,6 @@ class Field(MetaField('DummyField', (object,), {})): else: self.depends = make_depends(getattr(self.compute, '_depends', ())) - def _setup_regular_full(self, model): - """ Setup the inverse field(s) of ``self``. """ - pass - # # Setup of related fields # @@ -2182,8 +2182,8 @@ class _RelationalMulti(_Relational): for record in records: record[self.name] = record[self.name].filtered(accessible) - def _setup_regular_base(self, model): - super(_RelationalMulti, self)._setup_regular_base(model) + def _setup_regular_full(self, model): + super(_RelationalMulti, self)._setup_regular_full(model) if isinstance(self.domain, list): self.depends += tuple( self.name + '.' + arg[0] diff --git a/odoo/models.py b/odoo/models.py index 7707ffd2228..4eea8e8343d 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -2414,6 +2414,15 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})): cls._setup_done = True + # 5. determine and validate rec_name + if cls._rec_name: + assert cls._rec_name in cls._fields, \ + "Invalid rec_name %s for model %s" % (cls._rec_name, cls._name) + elif 'name' in cls._fields: + cls._rec_name = 'name' + elif 'x_name' in cls._fields: + cls._rec_name = 'x_name' + @api.model def _setup_fields(self): """ Setup the fields, except for recomputation triggers. """ @@ -2466,15 +2475,6 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})): # register constraints and onchange methods cls._init_constraints_onchanges() - # validate rec_name - if cls._rec_name: - assert cls._rec_name in cls._fields, \ - "Invalid rec_name %s for model %s" % (cls._rec_name, cls._name) - elif 'name' in cls._fields: - cls._rec_name = 'name' - elif 'x_name' in cls._fields: - cls._rec_name = 'x_name' - # make sure parent_order is set when necessary if cls._parent_store and not cls._parent_order: cls._parent_order = cls._order