From d8e2cd2082426b849f7e31f8ca7123fd39aca737 Mon Sep 17 00:00:00 2001 From: Jeremy Kersten Date: Fri, 15 May 2020 11:53:07 +0000 Subject: [PATCH 1/6] [IMP] website: perf - is_public_user use cached user_id on website --- addons/website/models/website.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/website/models/website.py b/addons/website/models/website.py index 41565fb031a..a5ff58608c1 100644 --- a/addons/website/models/website.py +++ b/addons/website/models/website.py @@ -654,7 +654,7 @@ class Website(models.Model): @api.model def is_public_user(self): - return request.env.user.id == request.website.user_id.id + return request.env.user.id == request.website._get_cached('user_id') @api.model def viewref(self, view_id, raise_if_not_found=True): From 84ff744eb0daffe4073dde47b885f2900aa524a1 Mon Sep 17 00:00:00 2001 From: Jeremy Kersten Date: Fri, 15 May 2020 11:54:03 +0000 Subject: [PATCH 2/6] [IMP] website_forum: perf - use the stored field instead to recompute it --- addons/website_forum/controllers/main.py | 2 +- addons/website_forum/views/website_forum.xml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/website_forum/controllers/main.py b/addons/website_forum/controllers/main.py index 51a4c00b0c1..3b5fbeae0b4 100644 --- a/addons/website_forum/controllers/main.py +++ b/addons/website_forum/controllers/main.py @@ -245,7 +245,7 @@ class WebsiteForum(WebsiteProfile): values.update({ 'main_object': question, 'question': question, - 'can_bump': (question.forum_id.allow_bump and not question.child_ids and (datetime.today() - question.write_date).days > 9), + 'can_bump': (question.forum_id.allow_bump and not question.child_count and (datetime.today() - question.write_date).days > 9), 'header': {'question_data': True}, 'filters': filters, 'reversed': reversed, diff --git a/addons/website_forum/views/website_forum.xml b/addons/website_forum/views/website_forum.xml index e94790873ee..d3ee186195c 100644 --- a/addons/website_forum/views/website_forum.xml +++ b/addons/website_forum/views/website_forum.xml @@ -288,7 +288,7 @@
 | - + Answer Answers @@ -1181,10 +1181,10 @@ -
+
- - Answer + + Answer Answers
From 52a0406a2c71621ce4c5fc550b9a8a5f695b29bf Mon Sep 17 00:00:00 2001 From: Jeremy Kersten Date: Tue, 19 May 2020 12:26:11 +0000 Subject: [PATCH 3/6] [IMP] website_forum: delay the set_viewed Try to make the update the latest possible, to minimize risk of concurrent update. Since it is not critical to loose a view, add the old value in where clause, to try to decrease the risk to alter at the same time a same row. --- addons/website_forum/controllers/main.py | 6 ++++-- addons/website_forum/models/forum.py | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/addons/website_forum/controllers/main.py b/addons/website_forum/controllers/main.py index 3b5fbeae0b4..c3d229135e6 100644 --- a/addons/website_forum/controllers/main.py +++ b/addons/website_forum/controllers/main.py @@ -235,8 +235,6 @@ class WebsiteForum(WebsiteProfile): if question.state == 'pending' and user.karma < forum.karma_post and question.create_uid != user: raise werkzeug.exceptions.NotFound() - # increment view counter - question.sudo().set_viewed() if question.parent_id: redirect_url = "/forum/%s/question/%s" % (slug(forum), slug(question.parent_id)) return werkzeug.utils.redirect(redirect_url, 301) @@ -252,6 +250,10 @@ class WebsiteForum(WebsiteProfile): }) if (request.httprequest.referrer or "").startswith(request.httprequest.url_root): values['back_button_url'] = request.httprequest.referrer + + # increment view counter + question.sudo().set_viewed() + return request.render("website_forum.post_description_full", values) @http.route('/forum//question//toggle_favourite', type='json', auth="user", methods=['POST'], website=True) diff --git a/addons/website_forum/models/forum.py b/addons/website_forum/models/forum.py index d77270c55a9..98cd889e12d 100644 --- a/addons/website_forum/models/forum.py +++ b/addons/website_forum/models/forum.py @@ -838,7 +838,8 @@ class Post(models.Model): return result def set_viewed(self): - self._cr.execute("""UPDATE forum_post SET views = views+1 WHERE id IN %s""", (self._ids,)) + self.ensure_one() + self._cr.execute("""UPDATE forum_post SET views = views+1 WHERE views = %s and id = %s""", (self.views, self.id,)) return True def get_access_action(self, access_uid=None): From 1b7f55a15e3b98ff26e45ccfb1999f3e97d6f680 Mon Sep 17 00:00:00 2001 From: Jeremy Kersten Date: Tue, 19 May 2020 12:37:06 +0000 Subject: [PATCH 4/6] [IMP] website_forum: perf - replace any by in Usinf of any seems not efficient in this case > timeit.timeit('any(7 == o for o in [1,3,5,7,9,12])', number=10000000) 6.556934245978482 > timeit.timeit('7 in set([1,3,5,7,9,12])', number=10000000) 2.78867393406108 > timeit.timeit('7 in [1,3,5,7,9,12]', number=10000000) 0.534781630965881 --- addons/website_forum/models/forum.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/website_forum/models/forum.py b/addons/website_forum/models/forum.py index 98cd889e12d..200a5b54c03 100644 --- a/addons/website_forum/models/forum.py +++ b/addons/website_forum/models/forum.py @@ -401,7 +401,7 @@ class Post(models.Model): def _get_uid_has_answered(self): for post in self: - post.uid_has_answered = any(answer.create_uid.id == post._uid for answer in post.child_ids) + post.uid_has_answered = post._uid in post.child_ids.create_uid.ids @api.depends('child_ids.is_correct') def _get_has_validated_answer(self): From f553d871fa903b62b642e63fe8e58a468ee6fa69 Mon Sep 17 00:00:00 2001 From: Jeremy Kersten Date: Tue, 19 May 2020 12:56:48 +0000 Subject: [PATCH 5/6] [FIX] website_forum: child_ids from current forum only Before this commit, we got all post where parent_id = self.id, whatever the forum_id from the post --- addons/website_forum/models/forum.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/website_forum/models/forum.py b/addons/website_forum/models/forum.py index 200a5b54c03..6758b931116 100644 --- a/addons/website_forum/models/forum.py +++ b/addons/website_forum/models/forum.py @@ -281,7 +281,7 @@ class Post(models.Model): is_correct = fields.Boolean('Correct', help='Correct answer or answer accepted') parent_id = fields.Many2one('forum.post', string='Question', ondelete='cascade', readonly=True, index=True) self_reply = fields.Boolean('Reply to own question', compute='_is_self_reply', store=True) - child_ids = fields.One2many('forum.post', 'parent_id', string='Post Answers') + child_ids = fields.One2many('forum.post', 'parent_id', string='Post Answers', domain=lambda self: [('forum_id', '=', self.forum_id.id)]) child_count = fields.Integer('Answers', compute='_get_child_count', store=True) uid_has_answered = fields.Boolean('Has Answered', compute='_get_uid_has_answered') has_validated_answer = fields.Boolean('Is answered', compute='_get_has_validated_answer', store=True) From 0d25f4f801f265a43ec16621629f656b2e5b29ec Mon Sep 17 00:00:00 2001 From: Jeremy Kersten Date: Tue, 19 May 2020 16:17:36 +0000 Subject: [PATCH 6/6] [IMP] website_forum: store the forum_count Cannot be a one2many, since website_id=False means that it is for all websites --- addons/website_forum/models/forum.py | 15 ++++++++++++++- addons/website_forum/models/website.py | 11 +++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/addons/website_forum/models/forum.py b/addons/website_forum/models/forum.py index 6758b931116..f8cf3c6ea02 100644 --- a/addons/website_forum/models/forum.py +++ b/addons/website_forum/models/forum.py @@ -177,7 +177,7 @@ class Forum(models.Model): @api.model def create(self, values): res = super(Forum, self.with_context(mail_create_nolog=True, mail_create_nosubscribe=True)).create(values) - res._set_default_faq() + res._set_default_faq() # will trigger a write and call update_website_count return res def write(self, vals): @@ -199,8 +199,15 @@ class Forum(models.Model): if 'active' in vals: # archiving/unarchiving a forum does it on its posts, too self.env['forum.post'].with_context(active_test=False).search([('forum_id', 'in', self.ids)]).write({'active': vals['active']}) + + if 'active' in vals or 'website_id' in vals: + self._update_website_count() return res + def unlink(self): + self._update_website_count() + return super(Forum, self).unlink() + @api.model def _tag_to_write_vals(self, tags=''): Tag = self.env['forum.tag'] @@ -238,6 +245,12 @@ class Forum(models.Model): 'url': self._compute_website_url(), } + @api.model + def _update_website_count(self): + for website in self.env['website'].sudo().search([]): + website.forums_count = self.env['forum.forum'].sudo().search_count(website.website_domain()) + + class Post(models.Model): _name = 'forum.post' diff --git a/addons/website_forum/models/website.py b/addons/website_forum/models/website.py index dcd937bf835..0957acb9cc7 100644 --- a/addons/website_forum/models/website.py +++ b/addons/website_forum/models/website.py @@ -1,19 +1,18 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from odoo import models, fields, _ +from odoo import models, fields, api, _ from odoo.addons.http_routing.models.ir_http import url_for class Website(models.Model): _inherit = 'website' - def _compute_field_forums_count(self): - Forum = self.env['forum.forum'] - for website in self: - website.forums_count = Forum.search_count(website.website_domain()) + @api.model + def get_default_forum_count(self): + self.forums_count = self.env['forum.forum'].search_count(self.website_domain()) - forums_count = fields.Integer(compute=_compute_field_forums_count) + forums_count = fields.Integer(readonly=True, default=get_default_forum_count) def get_suggested_controllers(self): suggested_controllers = super(Website, self).get_suggested_controllers()