[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:
@@ -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(
|
||||
{
|
||||
|
||||
@@ -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
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user