[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:
+9
-8
@@ -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
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user