diff options
Diffstat (limited to 'odoo')
| -rw-r--r-- | odoo/addons/test_new_api/models/test_new_api.py | 21 | ||||
| -rw-r--r-- | odoo/addons/test_new_api/security/ir.model.access.csv | 1 | ||||
| -rw-r--r-- | odoo/addons/test_new_api/tests/test_new_fields.py | 12 | ||||
| -rw-r--r-- | odoo/fields.py | 28 |
4 files changed, 54 insertions, 8 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 c0f7615f9d3..47df3602baa 100644 --- a/odoo/addons/test_new_api/models/test_new_api.py +++ b/odoo/addons/test_new_api/models/test_new_api.py @@ -595,6 +595,27 @@ class ComputeOnchangeLine(models.Model): required=True, ondelete='cascade') +class ComputeDynamicDepends(models.Model): + _name = 'test_new_api.compute.dynamic.depends' + _description = "Computed field with dynamic dependencies" + + name1 = fields.Char() + name2 = fields.Char() + name3 = fields.Char() + full_name = fields.Char(compute='_compute_full_name') + + def _get_full_name_fields(self): + # the fields to use are stored in a config parameter + depends = self.env['ir.config_parameter'].get_param('test_new_api.full_name', '') + return depends.split(',') if depends else [] + + @api.depends(lambda self: self._get_full_name_fields()) + def _compute_full_name(self): + fnames = self._get_full_name_fields() + for record in self: + record.full_name = ", ".join(filter(None, (record[fname] for fname in fnames))) + + class ComputeUnassigned(models.Model): _name = 'test_new_api.compute.unassigned' _description = "Model with computed fields left unassigned" diff --git a/odoo/addons/test_new_api/security/ir.model.access.csv b/odoo/addons/test_new_api/security/ir.model.access.csv index 37b088db27e..466b014f213 100644 --- a/odoo/addons/test_new_api/security/ir.model.access.csv +++ b/odoo/addons/test_new_api/security/ir.model.access.csv @@ -26,6 +26,7 @@ access_test_new_api_cascade,access_test_new_api_cascade,model_test_new_api_casca access_test_new_api_compute_readwrite,access_test_new_api_compute_readwrite,model_test_new_api_compute_readwrite,,1,1,1,1 access_test_new_api_compute_onchange,access_test_new_api_compute_onchange,model_test_new_api_compute_onchange,,1,1,1,1 access_test_new_api_compute_onchange_line,access_test_new_api_compute_onchange_line,model_test_new_api_compute_onchange_line,,1,1,1,1 +access_test_new_api_compute_dynamic_depends,access_test_new_api_compute_dynamic_depends,model_test_new_api_compute_dynamic_depends,,1,1,1,1 access_test_new_api_compute_unassigned,access_test_new_api_compute_unassigned,model_test_new_api_compute_unassigned,,1,1,1,1 access_test_new_api_binary_svg,access_test_new_api_binary_svg,model_test_new_api_binary_svg,,1,1,1,1 access_test_new_api_monetary_base,access_test_new_api_monetary_base,model_test_new_api_monetary_base,,1,1,1,1 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 3fb741f98b9..10993c52668 100644 --- a/odoo/addons/test_new_api/tests/test_new_fields.py +++ b/odoo/addons/test_new_api/tests/test_new_fields.py @@ -456,6 +456,18 @@ class TestFields(TransactionCaseWithUserDemo): record.foo = "Ho" self.assertEqual(record.baz, "<[Ho]>") + def test_12_dynamic_depends(self): + Model = self.registry['test_new_api.compute.dynamic.depends'] + self.assertEqual(Model.full_name.depends, ()) + + # the dependencies of full_name are stored in a config parameter + self.env['ir.config_parameter'].set_param('test_new_api.full_name', 'name1,name2') + + # this must re-evaluate the field's dependencies + self.env['base'].flush() + self.registry.setup_models(self.cr) + self.assertEqual(Model.full_name.depends, ('name1', 'name2')) + def test_13_inverse(self): """ test inverse computation of fields """ Category = self.env['test_new_api.category'] diff --git a/odoo/fields.py b/odoo/fields.py index e6325fe59d5..effdec15c78 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -222,8 +222,8 @@ class Field(MetaField('DummyField', (object,), {})): index = False # whether the field is indexed in database manual = False # whether the field is a custom field copy = True # whether the field is copied over by BaseModel.copy() - depends = None # collection of field dependencies - depends_context = None # collection of context key dependencies + _depends = None # collection of field dependencies + _depends_context = None # collection of context key dependencies recursive = False # whether self depends on itself compute = None # compute(recs) computes field on recs compute_sudo = False # whether field should be recomputed as superuser @@ -344,8 +344,13 @@ class Field(MetaField('DummyField', (object,), {})): if attrs.get('translate'): # by default, translatable fields are context-dependent attrs['depends_context'] = attrs.get('depends_context', ()) + ('lang',) + + # parameters 'depends' and 'depends_context' are stored in attributes + # '_depends' and '_depends_context', respectively if 'depends' in attrs: - attrs['depends'] = tuple(attrs['depends']) + attrs['_depends'] = tuple(attrs.pop('depends')) + if 'depends_context' in attrs: + attrs['_depends_context'] = tuple(attrs.pop('depends_context')) return attrs @@ -407,7 +412,10 @@ class Field(MetaField('DummyField', (object,), {})): def _setup_regular_full(self, model): """ Determine the dependencies and inverse field(s) of ``self``. """ - if self.depends is not None: + if self._depends is not None: + # the parameter 'depends' has priority over 'depends' on compute + self.depends = self._depends + self.depends_context = self._depends_context or () return # determine the functions implementing self.compute @@ -420,7 +428,7 @@ class Field(MetaField('DummyField', (object,), {})): # collect depends and depends_context depends = [] - depends_context = list(self.depends_context or ()) + depends_context = list(self._depends_context or ()) for func in funcs: deps = getattr(func, '_depends', ()) depends.extend(deps(model) if callable(deps) else deps) @@ -460,7 +468,9 @@ class Field(MetaField('DummyField', (object,), {})): raise TypeError("Type of related field %s is inconsistent with %s" % (self, field)) # determine dependencies, compute, inverse, and search - if self.depends is None: + if self._depends is not None: + self.depends = self._depends + else: self.depends = ('.'.join(self.related),) self.compute = self._compute_related if self.inherited or not (self.readonly or field.readonly): @@ -486,7 +496,9 @@ class Field(MetaField('DummyField', (object,), {})): self.required = True self._modules.update(field._modules) - if field.depends_context: + if self._depends_context is not None: + self.depends_context = self._depends_context + else: self.depends_context = field.depends_context def traverse_related(self, record): @@ -1883,7 +1895,7 @@ class Binary(Field): type = 'binary' prefetch = False # not prefetched by default - depends_context = ('bin_size',) # depends on context (content or size) + _depends_context = ('bin_size',) # depends on context (content or size) attachment = True # whether value is stored in attachment @property |
