From 76f699ca0be5ccb2167f856b6358e48da03e24eb Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Tue, 19 Oct 2021 15:38:35 +0000 Subject: [PATCH] [IMP] base: batch creation of custom related fields Before this commit, trying to create a field related to another field in the same batch raises an error, because the computation of the field 'related_field_id' cannot find the target field in the registry. The new approach consists in getting the target field from the database instead. It works when creating fields in batch, because all records are inserted into the database before the field is computated. This costs extra queries, but it allows to batch field creation and avoids multiple calls to setup_models() when creating a model with partner field in Studio. (see odoo/enterprise#21746) The creation of a simple custom related field (related="x.y") costs 3 additional queries to determine the target field: - 2 queries to get a given field on a given model - 1 query to get the first field's comodel Part-of: odoo/odoo#78514 --- odoo/addons/base/models/ir_model.py | 23 +++++++++++------------ odoo/addons/base/tests/test_ir_actions.py | 4 ++-- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/odoo/addons/base/models/ir_model.py b/odoo/addons/base/models/ir_model.py index 16c9b47a6e1..8d3cb9530d9 100644 --- a/odoo/addons/base/models/ir_model.py +++ b/odoo/addons/base/models/ir_model.py @@ -524,8 +524,7 @@ class IrModelFields(models.Model): def _compute_related_field_id(self): for rec in self: if rec.state == 'manual' and rec.related: - field = rec._related_field() - rec.related_field_id = self._get(field.model_name, field.name) + rec.related_field_id = rec._related_field() else: rec.related_field_id = False @@ -578,17 +577,17 @@ class IrModelFields(models.Model): ] def _related_field(self): - """ Return the ``Field`` instance corresponding to ``self.related``. """ + """ Return the ``ir.model.fields`` record corresponding to ``self.related``. """ names = self.related.split(".") last = len(names) - 1 - model = self.env[self.model or self.model_id.model] + model_name = self.model for index, name in enumerate(names): - field = model._fields.get(name) - if field is None: + field = self._get(model_name, name) + if not field: raise UserError(_("Unknown field name '%s' in related field '%s'") % (name, self.related)) - if index < last and not field.relational: + model_name = field.relation + if index < last and not field.relation: raise UserError(_("Non-relational field name '%s' in related field '%s'") % (name, self.related)) - model = model[name] return field @api.constrains('related') @@ -596,9 +595,9 @@ class IrModelFields(models.Model): for rec in self: if rec.state == 'manual' and rec.related: field = rec._related_field() - if field.type != rec.ttype: + if field.ttype != rec.ttype: raise ValidationError(_("Related field '%s' does not have type '%s'") % (rec.related, rec.ttype)) - if field.relational and field.comodel_name != rec.relation: + if field.relation != rec.relation: raise ValidationError(_("Related field '%s' does not have comodel '%s'") % (rec.related, rec.relation)) @api.onchange('related') @@ -608,8 +607,8 @@ class IrModelFields(models.Model): field = self._related_field() except UserError as e: return {'warning': {'title': _("Warning"), 'message': e}} - self.ttype = field.type - self.relation = field.comodel_name + self.ttype = field.ttype + self.relation = field.relation self.readonly = True @api.constrains('depends') diff --git a/odoo/addons/base/tests/test_ir_actions.py b/odoo/addons/base/tests/test_ir_actions.py index d046e1c1b16..379af5f6b78 100644 --- a/odoo/addons/base/tests/test_ir_actions.py +++ b/odoo/addons/base/tests/test_ir_actions.py @@ -514,8 +514,8 @@ class TestCustomFields(common.TransactionCase): 'store': True, }) - # same with a related field, it only takes 2 extra queries - with self.assertQueryCount(query_count + 2): + # same with a related field, it only takes 5 extra queries + with self.assertQueryCount(query_count + 5): self.env.registry.clear_caches() self.env['ir.model.fields'].create({ 'model_id': model_id,