[FIX] models, fields: make read add secondary records for prefetching

Make the following statements add secondary records (values of relational fields)
in the prefetching object of ``self``:

    self.read(fields)
    self.partner_id             # implicitly invokes read()

This makes sure that traversing relational fields on records automatically
feeds the prefetching of secondary records.
This commit is contained in:
Raphael Collet
2016-04-25 13:37:11 +02:00
parent f9b08f09b2
commit d035828778
2 changed files with 16 additions and 13 deletions
+9 -8
View File
@@ -765,7 +765,8 @@ class Field(object):
def convert_to_cache(self, value, record, validate=True):
""" Convert ``value`` to the cache format; ``value`` may come from an
assignment, or have the format of methods :meth:`BaseModel.read` or
:meth:`BaseModel.write`.
:meth:`BaseModel.write`. If the value represents a recordset, it should
be added for prefetching on ``record``.
:param bool validate: when True, field-specific validation of ``value``
will be performed
@@ -1574,10 +1575,10 @@ class Reference(Selection):
def convert_to_cache(self, value, record, validate=True):
if isinstance(value, BaseModel):
if not validate or (value._name in self.get_values(record.env) and len(value) <= 1):
return value.with_env(record.env) or False
return value.with_env(record.env).with_prefetch(record._prefetch) or False
elif isinstance(value, basestring):
res_model, res_id = value.split(',')
return record.env[res_model].browse(int(res_id))
return record.env[res_model].browse(int(res_id), record._prefetch)
elif not value:
return False
raise ValueError("Wrong value for %s: %r" % (self, value))
@@ -1689,13 +1690,13 @@ class Many2one(_Relational):
def convert_to_cache(self, value, record, validate=True):
if isinstance(value, (NoneType, int, long)):
return record.env[self.comodel_name].browse(value)
return record.env[self.comodel_name].browse(value, record._prefetch)
if isinstance(value, BaseModel):
if not validate or (value._name == self.comodel_name and len(value) <= 1):
return value.with_env(record.env)
return value.with_env(record.env).with_prefetch(record._prefetch)
raise ValueError("Wrong value for %s: %r" % (self, value))
elif isinstance(value, tuple):
return record.env[self.comodel_name].browse(value[0])
return record.env[self.comodel_name].browse(value[0], record._prefetch)
elif isinstance(value, dict):
return record.env[self.comodel_name].new(value)
else:
@@ -1758,7 +1759,7 @@ class _RelationalMulti(_Relational):
def convert_to_cache(self, value, record, validate=True):
if isinstance(value, BaseModel):
if not validate or (value._name == self.comodel_name):
return value.with_env(record.env)
return value.with_env(record.env).with_prefetch(record._prefetch)
elif isinstance(value, list):
# value is a list of record ids or commands
comodel = record.env[self.comodel_name]
@@ -1788,7 +1789,7 @@ class _RelationalMulti(_Relational):
else:
ids.add(command)
# return result as a recordset
return comodel.browse(list(ids))
return comodel.browse(list(ids), record._prefetch)
elif not value:
return record.env[self.comodel_name]
raise ValueError("Wrong value for %s: %s" % (self, value))
+7 -5
View File
@@ -3380,7 +3380,8 @@ class BaseModel(object):
else:
_logger.warning("%s.read() with unknown field '%s'", self._name, name)
# fetch stored fields from the database to the cache
# fetch stored fields from the database to the cache; this should feed
# the prefetching of secondary records
self._read_from_database(stored, inherited)
# retrieve results from records; this takes values from the cache and
@@ -3449,6 +3450,7 @@ class BaseModel(object):
# fetch records with read()
assert self in records and field in fs
records = records.with_prefetch(self._prefetch)
result = []
try:
result = records.read([f.name for f in fs], load='_classic_write')
@@ -3459,7 +3461,7 @@ class BaseModel(object):
# check the cache, and update it if necessary
if field not in self._cache:
for values in result:
record = self.browse(values.pop('id'))
record = self.browse(values.pop('id'), self._prefetch)
record._cache.update(record._convert_to_cache(values, validate=False))
if not self._cache.contains(field):
e = AccessError("No value found for %s.%s" % (self, field.name))
@@ -3545,7 +3547,7 @@ class BaseModel(object):
# store result in cache for POST fields
for vals in result:
record = self.browse(vals['id'])
record = self.browse(vals['id'], self._prefetch)
record._cache.update(record._convert_to_cache(vals, validate=False))
# determine the fields that must be processed now;
@@ -3587,7 +3589,7 @@ class BaseModel(object):
# store result in cache
for vals in result:
record = self.browse(vals.pop('id'))
record = self.browse(vals.pop('id'), self._prefetch)
record._cache.update(record._convert_to_cache(vals, validate=False))
# store failed values in cache for the records that could not be read
@@ -5656,7 +5658,7 @@ class BaseModel(object):
:param validate: whether values must be checked
"""
fields = self._fields
target = self if update else self.browse()
target = self if update else self.browse([], self._prefetch)
return {
name: fields[name].convert_to_cache(value, target, validate=validate)
for name, value in values.iteritems()