[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
This commit is contained in:
committed by
Xavier-Do
parent
e966beb3ca
commit
76f699ca0b
@@ -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')
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user