Skip to content
Permalink
Browse files

[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 #36476

Signed-off-by: Christophe Simonis <chs@odoo.com>
  • Loading branch information...
rco-odoo committed Sep 5, 2019
1 parent 71cc792 commit eef48811ffe5328e53b143e91b67cbc85ba7d674
Showing with 28 additions and 15 deletions.
  1. +7 −0 odoo/addons/test_new_api/tests/test_new_fields.py
  2. +6 −6 odoo/fields.py
  3. +15 −9 odoo/models.py
@@ -80,6 +80,13 @@ def test_10_computed_custom(self):
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
@@ -490,6 +490,10 @@ def setup_full(self, model):

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``. """
if self.depends is not None:
return

@@ -507,10 +511,6 @@ def get_depends(func):
else:
self.depends = tuple(get_depends(self.compute))

def _setup_regular_full(self, model):
""" Setup the inverse field(s) of ``self``. """
pass

#
# Setup of related fields
#
@@ -2428,8 +2428,8 @@ def _compute_related(self, records):
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]
@@ -2622,6 +2622,15 @@ def _setup_base(self):

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. """
@@ -2646,6 +2655,12 @@ def _setup_fields(self):
del cls._fields[name]
delattr(cls, name)

# fix up _rec_name
if 'x_name' in bad_fields and cls._rec_name == 'x_name':
cls._rec_name = None
field = cls._fields['display_name']
field.depends = tuple(name for name in field.depends if name != 'x_name')

# map each field to the fields computed with the same method
groups = defaultdict(list)
for field in cls._fields.values():
@@ -2674,15 +2689,6 @@ def _setup_complete(self):
# 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'

@api.model
def fields_get(self, allfields=None, attributes=None):
""" fields_get([fields][, attributes])

0 comments on commit eef4881

Please sign in to comment.
You can’t perform that action at this time.