From c3b7eac631bd7f29df72683bdc7f089daf6b1973 Mon Sep 17 00:00:00 2001 From: Florian Charlier Date: Mon, 15 Jan 2024 12:02:36 +0100 Subject: [PATCH] [FIX] website_forum: avoid `search` in a loop for last post MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Computation of the last post shouldn't be done with a db request for each forum but can be batched. Technical note: As it is likely that `post_ids` is not yet fetched when we're accessing `last_post_id` we chose not to early return if no forum in `self` included posts already. Version choice: We chose this version to merge this as it is the one where forum was taken over, and _read_group refactored. A test for this computation is also added. Task-3685002 closes odoo/odoo#150444 X-original-commit: ba3af942deee4818edb32d08b9bb07652253a029 Signed-off-by: Warnon Aurélien (awa) Signed-off-by: Florian Charlier (flch) --- addons/website_forum/models/forum_forum.py | 10 ++++++---- .../tests/test_forum_internals.py | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/addons/website_forum/models/forum_forum.py b/addons/website_forum/models/forum_forum.py index 1bc89788b3f..a1153ce4a61 100644 --- a/addons/website_forum/models/forum_forum.py +++ b/addons/website_forum/models/forum_forum.py @@ -198,11 +198,13 @@ class Forum(models.Model): @api.depends('post_ids') def _compute_last_post_id(self): + last_forums_posts = self.env['forum.post']._read_group( + [('forum_id', 'in', self.ids), ('parent_id', '=', False), ('state', '=', 'active')], + groupby=['forum_id'], aggregates=['id:max'], + ) + forum_to_last_post_id = {forum.id: last_post_id for forum, last_post_id in last_forums_posts} for forum in self: - forum.last_post_id = forum.post_ids.search( - [('forum_id', '=', forum.id), ('parent_id', '=', False), ('state', '=', 'active')], - order='create_date desc', limit=1, - ) + forum.last_post_id = forum_to_last_post_id.get(forum.id, False) @api.depends('post_ids.state', 'post_ids.views', 'post_ids.child_count', 'post_ids.favourite_count') def _compute_forum_statistics(self): diff --git a/addons/website_forum/tests/test_forum_internals.py b/addons/website_forum/tests/test_forum_internals.py index 772edad458e..785239ecee9 100644 --- a/addons/website_forum/tests/test_forum_internals.py +++ b/addons/website_forum/tests/test_forum_internals.py @@ -59,6 +59,24 @@ class TestForumInternals(TestForumCommon): self.assertEqual(website_2.forum_count, 6, '6 global forums') + def test_website_forum_last_post_id(self): + """Check that each forum's last post is computed correctly and efficiently.""" + test_forums = self.base_forum | self.forum + new_posts = self.env["forum.post"].create([{ + 'name': f'New Post {forum_post_idx}', + 'forum_id': forum.id, + } for forum_post_idx, forum in enumerate(test_forums)]) + + with self.assertQueryCount(1): + self.assertEqual(test_forums.last_post_id.ids, new_posts.ids) + + another_post = self.env["forum.post"].create([{ + 'name': 'Another New Post', + 'forum_id': self.base_forum.id, + }]) + with self.assertQueryCount(1): + self.assertEqual(test_forums.last_post_id.ids, (another_post | new_posts[1]).ids) + @tagged('forum_internals') class TestPostInternals(TestForumCommon):