diff --git a/odoo/addons/base/models/ir_ui_view.py b/odoo/addons/base/models/ir_ui_view.py index ba63d2afadf..060e28bc463 100644 --- a/odoo/addons/base/models/ir_ui_view.py +++ b/odoo/addons/base/models/ir_ui_view.py @@ -376,6 +376,8 @@ actual arch. # Any exception raised below will cause a transaction rollback. self = self.with_context(check_field_names=True) for view in self: + if not view.arch: + continue view_arch = etree.fromstring(view.arch.encode('utf-8')) view._valid_inheritance(view_arch) view_def = view.read_combined(['arch']) diff --git a/odoo/addons/test_new_api/models.py b/odoo/addons/test_new_api/models.py index f5057eebc49..18bcbdb8c51 100644 --- a/odoo/addons/test_new_api/models.py +++ b/odoo/addons/test_new_api/models.py @@ -148,6 +148,13 @@ class Message(models.Model): message.name = self._context.get('compute_name', "[%s] %s" % (message.discussion.name or '', message.author.name or '')) + @api.constrains('name') + def _check_name(self): + # dummy constraint to check on computed field + for message in self: + if message.name.startswith("[X]"): + raise ValidationError("No way!") + @api.depends('author.name', 'discussion.name', 'body') def _compute_display_name(self): for message in self: 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 9b17933397a..e65b20ed561 100644 --- a/odoo/addons/test_new_api/tests/test_new_fields.py +++ b/odoo/addons/test_new_api/tests/test_new_fields.py @@ -8,7 +8,7 @@ from PIL import Image import psycopg2 from odoo import fields -from odoo.exceptions import AccessError, UserError +from odoo.exceptions import AccessError, UserError, ValidationError from odoo.tests import common from odoo.tools import mute_logger, float_repr from odoo.tools.date_utils import add, subtract, start_of, end_of @@ -439,7 +439,7 @@ class TestFields(common.TransactionCase): # remove oneself from discussion participants: we can no longer create # messages in discussion discussion.participants -= self.env.user - with self.assertRaises(Exception): + with self.assertRaises(ValidationError): self.env['test_new_api.message'].create({'discussion': discussion.id, 'body': 'Whatever'}) # make sure that assertRaises() does not leave fields to recompute @@ -450,6 +450,12 @@ class TestFields(common.TransactionCase): discussion.participants += self.env.user self.env['test_new_api.message'].create({'discussion': discussion.id, 'body': 'Whatever'}) + # check constraint on recomputed field + self.assertTrue(discussion.messages) + with self.assertRaises(ValidationError): + discussion.name = "X" + discussion.flush() + def test_20_float(self): """ test rounding of float fields """ record = self.env['test_new_api.mixed'].create({}) diff --git a/odoo/models.py b/odoo/models.py index 858a9a91b0e..bc9a153a77b 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -3708,6 +3708,11 @@ Fields: else: field.compute(self) + if field.store and any(self._ids): + # check constraints of the fields that have been computed + fnames = [f.name for f in self._field_computed[field]] + self.filtered('id')._validate_fields(fnames) + def _parent_store_create(self): """ Set the parent_path field on ``self`` after its creation. """ if not self._parent_store: