[FIX] core: sorted of new records + prefetch

BaseModel's sorted() has two problems:
- It breaks the prefetch of self for no reason
- When it is called without an argument, it filters out new records
because the search() used in sorted() doesn't return new records.

Keep the same prefetch as self to fix the first problem.
We partially fix/support the second issue, we just avoid filtering out
new records (but we don't actually sort them)

closes odoo/odoo#157145

X-original-commit: 0551c3b7e8e1469dabdb19d6420c544a1654fec5
Signed-off-by: Rémy Voet (ryv) <ryv@odoo.com>
This commit is contained in:
Rémy Voet (ryv)
2024-03-12 10:34:51 +00:00
parent 7c54283632
commit b9bfc0bb6e
2 changed files with 42 additions and 5 deletions
+32
View File
@@ -670,6 +670,38 @@ class TestAPI(SavepointCaseWithUserDemo):
by_name_ids = [p.id for p in sorted(ps, key=lambda p: p.name, reverse=True)]
self.assertEqual(ps.sorted('name', reverse=True).ids, by_name_ids)
# sorted doesn't filter out new records but don't sort them either (limitation)
new_p = self.env['res.partner'].new({
'child_ids': [
Command.create({'name': 'z'}),
Command.create({'name': 'a'}),
],
})
self.assertEqual(len(new_p.child_ids.sorted()), 2)
# sorted keeps the _prefetch_ids
partners_with_children = self.env['res.partner'].create([
{
'name': 'required',
'child_ids': [
Command.create({'name': 'z'}),
Command.create({'name': 'a'}),
],
},
{
'name': 'required',
'child_ids': [
Command.create({'name': 'z'}),
Command.create({'name': 'a'}),
],
},
])
partners_with_children.invalidate_model(['name'])
# Only one query to fetch name of children of each partner
with self.assertQueryCount(1):
for partner in partners_with_children:
partner.child_ids.sorted('id').mapped('name')
def test_group_on(self):
p0, p1, p2 = self.env['res.partner'].create([
{'name': "bob", 'function': "guest"},
+10 -5
View File
@@ -6268,11 +6268,16 @@ class BaseModel(metaclass=MetaModel):
records.sorted(key=lambda r: r.name)
"""
if key is None:
recs = self.search([('id', 'in', self.ids)])
return self.browse(reversed(recs._ids)) if reverse else recs
if isinstance(key, str):
key = itemgetter(key)
return self.browse(item.id for item in sorted(self, key=key, reverse=reverse))
if any(self._ids):
ids = self.search([('id', 'in', self.ids)])._ids
else: # Don't support new ids because search() doesn't work on new records
ids = self._ids
ids = tuple(reversed(ids)) if reverse else ids
else:
if isinstance(key, str):
key = itemgetter(key)
ids = tuple(item.id for item in sorted(self, key=key, reverse=reverse))
return self.__class__(self.env, ids, self._prefetch_ids)
def update(self, values):
""" Update the records in ``self`` with ``values``. """