[FIX] web: web_read() on new records with _inherits

This commit partly reverts 59afbf6686 and
provides an alternative solution.  In this solution, records.web_read()
returns a list of dicts where the key 'id' corresponds to each record.id
in records, which enables to reliably relate each record to its values.

This also fixes the implementation of web_read() on new records where
the fields contain a reference field with some context.

closes odoo/odoo#128878

Signed-off-by: Raphael Collet <rco@odoo.com>
This commit is contained in:
Raphael Collet
2023-07-18 19:28:13 +02:00
parent f8bbec56f2
commit 96a98f4f4c
4 changed files with 35 additions and 7 deletions
+10 -4
View File
@@ -90,13 +90,19 @@ class Base(models.AbstractModel):
if fields_to_read == ['id']:
# if we request to read only the ids, we have them already so we can build the return dictionaries immediately
# this also avoid a call to read on the co-model that might have different access rules
values_list = [{'id': record._origin.id} for record in self]
values_list = [{'id': id_} for id_ in self._ids]
else:
values_list: List[Dict] = self.read(fields_to_read, load=None)
if not values_list:
return values_list
def cleanup(vals: Dict) -> Dict:
""" Fixup vals['id'] of a new record. """
if not vals['id']:
vals['id'] = vals['id'].origin or False
return vals
for field_name, field_spec in specification.items():
if not field_spec:
continue
@@ -111,16 +117,16 @@ class Base(models.AbstractModel):
extra_fields.pop('display_name', None)
many2one_data = {
vals['id']: vals
vals['id']: cleanup(vals)
for vals in co_records.web_read(extra_fields)
}
if 'display_name' in field_spec['fields']:
for rec in co_records.sudo():
many2one_data[rec._origin.id]['display_name'] = rec.display_name
many2one_data[rec.id]['display_name'] = rec.display_name
for values in values_list:
if not values[field_name]:
if values[field_name] is False:
continue
values[field_name] = many2one_data[values[field_name]]
@@ -164,7 +164,7 @@ class TestUnityRead(TransactionCase):
'login': {},
})
self.assertEqual(result, [{
'id': new_account._origin.id,
'id': new_account.id,
'name': new_account.name,
'login': new_account.login,
}])
@@ -176,7 +176,7 @@ class TestUnityRead(TransactionCase):
'person_id': {'fields': {'name': {}}},
})
self.assertEqual(result, [{
'id': new_account._origin.id,
'id': new_account.id,
'person_id': {
'id': new_account.person_id._origin.id,
'name': new_account.person_id.name,
@@ -561,6 +561,26 @@ class TestUnityRead(TransactionCase):
}
])
def test_reference_fields_respect_context_with_new_record(self):
new_course = self.course.new(origin=self.course)
read = new_course.web_read(
{
'reference':
{
'fields': {'display_name': {}},
'context': {'special': 'yes'}
}
})
self.assertEqual(read, [
{
'id': new_course.id,
'reference': {
'id': {'id': self.lesson_day1.id, 'model': self.lesson_day1._name},
'display_name': 'special first day'
}
}
])
def test_reference_fields_extra_fields(self):
read = self.course.web_read(
{
+2
View File
@@ -3037,6 +3037,8 @@ class Many2one(_Relational):
except MissingError:
# Should not happen, unless the foreign key is missing.
return False
elif self.delegate:
return value.id
else:
return value._origin.id
+1 -1
View File
@@ -3355,7 +3355,7 @@ class BaseModel(metaclass=MetaModel):
The current method is different from `read` because it retrieves its
values from the cache without doing a query when it is avoidable.
"""
data = [(record, {'id': record._origin.id}) for record in self]
data = [(record, {'id': record.id}) for record in self]
use_display_name = (load == '_classic_read')
for name in fnames:
field = self._fields[name]