[FIX] website: remove force prefetch for translate fields
Issue ----- When website is installed, the rendering of template uses a side effect of the ORM cache (cache shared between sudoed env vs non-sudoed env) and the fields prefetching feature to work correctly. The `self.visibility` in (`_handle_visibility`, website/ir_ui_view.py) is done in sudo mode, then it will fetch all prefetchable fields and put them in the cache (that will be read in non-sudo mode in the render of the template). Another example of issue related to this: https://github.com/odoo/odoo/pull/83341. Because of this, the fields of mixin `website.seo.metadata` were forced to be prefetchable (the default for translate is to be not prefetchable since https://github.com/odoo/odoo/pull/82896), which causes a useless LEFT JOIN on "ir_translation" in most of business flow. Fix --- Remove the `prefetch=True` on mixin fields, and add a extra read to fill the cache in case of website rendering. It also allows to read these fields at the same time. Part-of: odoo/odoo#85220
This commit is contained in:
@@ -70,7 +70,7 @@ class TestCrmPerformance(CrmPerformanceCase):
|
||||
country_be = self.env.ref('base.be')
|
||||
lang_be = self.env['res.lang']._lang_get('fr_BE')
|
||||
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(user_sales_leads=188): # tcf only: 173 - com runbot: 174/175
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(user_sales_leads=190): # tcf only: 175 - com runbot: 176/177
|
||||
self.env.cr._now = self.reference_now # force create_date to check schedulers
|
||||
with Form(self.env['crm.lead']) as lead_form:
|
||||
lead_form.country_id = country_be
|
||||
@@ -89,7 +89,7 @@ class TestCrmPerformance(CrmPerformanceCase):
|
||||
@warmup
|
||||
def test_lead_create_form_partner(self):
|
||||
""" Test a single lead creation using Form with a partner """
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(user_sales_leads=193): # tcf only: 178 - com runbot: 179/180
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(user_sales_leads=195): # tcf only: 180 - com runbot: 181/182
|
||||
self.env.cr._now = self.reference_now # force create_date to check schedulers
|
||||
with Form(self.env['crm.lead']) as lead_form:
|
||||
lead_form.partner_id = self.partners[0]
|
||||
|
||||
@@ -52,7 +52,7 @@ class TestEventPerformance(EventPerformanceCase):
|
||||
batch_size = 20
|
||||
|
||||
# simple without type involved + website
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=5488): # tef only: 5062 (5058) - com runbot: 5062 - ent runbot 5482-5487
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=5495): # tef only: 5069 (5065) - com runbot: 5069 - ent runbot 5489-5494
|
||||
self.env.cr._now = self.reference_now # force create_date to check schedulers
|
||||
event_values = [
|
||||
dict(self.event_base_vals,
|
||||
@@ -89,7 +89,7 @@ class TestEventPerformance(EventPerformanceCase):
|
||||
event_type = self.env['event.type'].browse(self.test_event_type.ids)
|
||||
|
||||
# complex with type + website
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=5601): # tef only: 5171 - com runbot: 5175 - ent runbot 5595-5600
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=5608): # tef only: 5178 - com runbot: 5182 - ent runbot 5602-5607
|
||||
self.env.cr._now = self.reference_now # force create_date to check schedulers
|
||||
event_values = [
|
||||
dict(self.event_base_vals,
|
||||
@@ -107,7 +107,7 @@ class TestEventPerformance(EventPerformanceCase):
|
||||
has_social = 'social_menu' in self.env['event.event'] # otherwise view may crash in enterprise
|
||||
|
||||
# no type, no website
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=226): # tef only: 176 - com runbot: 176
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=234): # tef only: 184 - com runbot: 184
|
||||
self.env.cr._now = self.reference_now # force create_date to check schedulers
|
||||
with Form(self.env['event.event']) as event_form:
|
||||
event_form.name = 'Test Event'
|
||||
@@ -125,7 +125,7 @@ class TestEventPerformance(EventPerformanceCase):
|
||||
has_social = 'social_menu' in self.env['event.event'] # otherwise view may crash in enterprise
|
||||
|
||||
# no type, website
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=735): # tef only: 622 - com runbot: 623
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=750): # tef only: 637 - com runbot: 638
|
||||
self.env.cr._now = self.reference_now # force create_date to check schedulers
|
||||
with Form(self.env['event.event']) as event_form:
|
||||
event_form.name = 'Test Event'
|
||||
@@ -144,7 +144,7 @@ class TestEventPerformance(EventPerformanceCase):
|
||||
has_social = 'social_menu' in self.env['event.event'] # otherwise view may crash in enterprise
|
||||
|
||||
# type and website
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=770): # tef only: 660 - com runbot: 663
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=783): # tef only: 673 - com runbot: 676
|
||||
self.env.cr._now = self.reference_now # force create_date to check schedulers
|
||||
with Form(self.env['event.event']) as event_form:
|
||||
event_form.name = 'Test Event'
|
||||
@@ -172,7 +172,7 @@ class TestEventPerformance(EventPerformanceCase):
|
||||
def test_event_create_single_notype_website(self):
|
||||
""" Test a single event creation """
|
||||
# simple without type involved + website
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=377): # tef only: 351 (346) - com runbot: 350 - ent runbot 376
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=384): # tef only: 358 (353) - com runbot: 357 - ent runbot 383
|
||||
self.env.cr._now = self.reference_now # force create_date to check schedulers
|
||||
event_values = dict(
|
||||
self.event_base_vals,
|
||||
@@ -203,7 +203,7 @@ class TestEventPerformance(EventPerformanceCase):
|
||||
event_type = self.env['event.type'].browse(self.test_event_type.ids)
|
||||
|
||||
# complex with type + website
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=413): # tef only: 388 (382) - com runbot: 386 - ent runbot 412
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=420): # tef only: 395 (389) - com runbot: 393 - ent runbot 419
|
||||
self.env.cr._now = self.reference_now # force create_date to check schedulers
|
||||
event_values = dict(
|
||||
self.event_base_vals,
|
||||
@@ -225,7 +225,7 @@ class TestRegistrationPerformance(EventPerformanceCase):
|
||||
"""
|
||||
event = self.env['event.event'].browse(self.test_event.ids)
|
||||
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=720): # tef only: 673 - com runbot 716 - ent runbot 719
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=721): # tef only: 674 - com runbot 717 - ent runbot 720
|
||||
self.env.cr._now = self.reference_now # force create_date to check schedulers
|
||||
registration_values = [
|
||||
dict(reg_data,
|
||||
@@ -249,7 +249,7 @@ class TestRegistrationPerformance(EventPerformanceCase):
|
||||
"""
|
||||
event = self.env['event.event'].browse(self.test_event.ids)
|
||||
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=244): # tef only: 200 - com runbot 239 - ent runbot 243
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=245): # tef only: 201 - com runbot 240 - ent runbot 245
|
||||
self.env.cr._now = self.reference_now # force create_date to check schedulers
|
||||
registration_values = [
|
||||
dict(reg_data,
|
||||
@@ -271,7 +271,7 @@ class TestRegistrationPerformance(EventPerformanceCase):
|
||||
form like) """
|
||||
event = self.env['event.event'].browse(self.test_event.ids)
|
||||
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=730): # tef only: 684 - com runbot 727
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=731): # tef only: 685 - com runbot 728
|
||||
self.env.cr._now = self.reference_now # force create_date to check schedulers
|
||||
registration_values = [
|
||||
dict(reg_data,
|
||||
@@ -292,7 +292,7 @@ class TestRegistrationPerformance(EventPerformanceCase):
|
||||
""" Test a single registration creation using Form """
|
||||
event = self.env['event.event'].browse(self.test_event.ids)
|
||||
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=229): # tef only: 209 - com runbot 215
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=230): # tef only: 210 - com runbot 216
|
||||
self.env.cr._now = self.reference_now # force create_date to check schedulers
|
||||
with Form(self.env['event.registration']) as reg_form:
|
||||
reg_form.event_id = event
|
||||
@@ -308,7 +308,7 @@ class TestRegistrationPerformance(EventPerformanceCase):
|
||||
""" Test a single registration creation using Form """
|
||||
event = self.env['event.event'].browse(self.test_event.ids)
|
||||
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=232): # tef only: 212 - com runbot 217
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=233): # tef only: 213 - com runbot 218
|
||||
self.env.cr._now = self.reference_now # force create_date to check schedulers
|
||||
with Form(self.env['event.registration']) as reg_form:
|
||||
reg_form.event_id = event
|
||||
@@ -321,7 +321,7 @@ class TestRegistrationPerformance(EventPerformanceCase):
|
||||
""" Test a single registration creation using Form """
|
||||
event = self.env['event.event'].browse(self.test_event.ids)
|
||||
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=141): # tef only: 123 - com runbot 125
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=142): # tef only: 124 - com runbot 126
|
||||
self.env.cr._now = self.reference_now # force create_date to check schedulers
|
||||
with Form(self.env['event.registration'].with_context(event_lead_rule_skip=True)) as reg_form:
|
||||
reg_form.event_id = event
|
||||
@@ -335,7 +335,7 @@ class TestRegistrationPerformance(EventPerformanceCase):
|
||||
event = self.env['event.event'].browse(self.test_event.ids)
|
||||
|
||||
# simple customer data
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=141): # tef only: 134 - com runbot 139
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=142): # tef only: 135 - com runbot 140
|
||||
self.env.cr._now = self.reference_now # force create_date to check schedulers
|
||||
registration_values = dict(
|
||||
self.customer_data[0],
|
||||
@@ -349,7 +349,7 @@ class TestRegistrationPerformance(EventPerformanceCase):
|
||||
event = self.env['event.event'].browse(self.test_event.ids)
|
||||
|
||||
# partner-based customer
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=148): # tef only: 142 - com runbot 147
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=149): # tef only: 143 - com runbot 148
|
||||
self.env.cr._now = self.reference_now # force create_date to check schedulers
|
||||
registration_values = {
|
||||
'event_id': event.id,
|
||||
@@ -364,7 +364,7 @@ class TestRegistrationPerformance(EventPerformanceCase):
|
||||
event = self.env['event.event'].browse(self.test_event.ids)
|
||||
|
||||
# partner-based customer
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=59): # tef only: 55 - com runbot 57
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=60): # tef only: 56 - com runbot 58
|
||||
self.env.cr._now = self.reference_now # force create_date to check schedulers
|
||||
registration_values = {
|
||||
'event_id': event.id,
|
||||
@@ -379,7 +379,7 @@ class TestRegistrationPerformance(EventPerformanceCase):
|
||||
event = self.env['event.event'].browse(self.test_event.ids)
|
||||
|
||||
# website customer data
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=150): # tef only: 141 - com runbot 146
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=151): # tef only: 142 - com runbot 147
|
||||
self.env.cr._now = self.reference_now # force create_date to check schedulers
|
||||
registration_values = dict(
|
||||
self.website_customer_data[0],
|
||||
@@ -428,7 +428,7 @@ class TestOnlineEventPerformance(EventPerformanceCase, UtilPerf):
|
||||
# website customer data
|
||||
with freeze_time(self.reference_now):
|
||||
self.authenticate('user_eventmanager', 'user_eventmanager')
|
||||
with self.assertQueryCount(default=65): # tef only: 64 (+1 ent)
|
||||
with self.assertQueryCount(default=69): # tef only: 68 (+1 ent)
|
||||
self._test_url_open('/event/%i' % self.test_event.id)
|
||||
|
||||
@warmup
|
||||
@@ -436,7 +436,7 @@ class TestOnlineEventPerformance(EventPerformanceCase, UtilPerf):
|
||||
# website customer data
|
||||
with freeze_time(self.reference_now):
|
||||
self.authenticate(None, None)
|
||||
with self.assertQueryCount(default=43): # tef only: 43
|
||||
with self.assertQueryCount(default=47): # tef only: 47
|
||||
self._test_url_open('/event/%i' % self.test_event.id)
|
||||
|
||||
@warmup
|
||||
@@ -444,7 +444,7 @@ class TestOnlineEventPerformance(EventPerformanceCase, UtilPerf):
|
||||
# website customer data
|
||||
with freeze_time(self.reference_now):
|
||||
self.authenticate('user_eventmanager', 'user_eventmanager')
|
||||
with self.assertQueryCount(default=51): # tef only: 50 (+1 ent)
|
||||
with self.assertQueryCount(default=53): # tef only: 52 (+1 ent)
|
||||
self._test_url_open('/event')
|
||||
|
||||
@warmup
|
||||
@@ -452,7 +452,7 @@ class TestOnlineEventPerformance(EventPerformanceCase, UtilPerf):
|
||||
# website customer data
|
||||
with freeze_time(self.reference_now):
|
||||
self.authenticate(None, None)
|
||||
with self.assertQueryCount(default=32): # tef only: 32
|
||||
with self.assertQueryCount(default=34): # tef only: 34
|
||||
self._test_url_open('/event')
|
||||
|
||||
# @warmup
|
||||
|
||||
@@ -658,7 +658,7 @@ class Website(Home):
|
||||
fields.extend(['website_indexed', 'website_id'])
|
||||
|
||||
record = request.env[res_model].browse(res_id)
|
||||
res = record._read_format(fields)[0]
|
||||
res = record.read(fields)[0]
|
||||
res['has_social_default_image'] = request.website.has_social_default_image
|
||||
|
||||
if res_model not in ('website.page', 'ir.ui.view') and 'seo_name' in record: # allow custom slugify
|
||||
|
||||
@@ -389,7 +389,7 @@ class View(models.Model):
|
||||
(request.website.is_public_user() or self.id not in request.session.get('views_unlock', [])):
|
||||
pwd = request.params.get('visibility_password')
|
||||
if pwd and self.env.user._crypt_context().verify(
|
||||
pwd, self.sudo().visibility_password):
|
||||
pwd, self.visibility_password):
|
||||
request.session.setdefault('views_unlock', list()).append(self.id)
|
||||
else:
|
||||
error = werkzeug.exceptions.Forbidden('website_visibility_password_required')
|
||||
@@ -469,6 +469,10 @@ class View(models.Model):
|
||||
editable=editable,
|
||||
))
|
||||
|
||||
# fetch non-prefetchable fields of the mixin SeoMetadata, as they
|
||||
# will be read later in non-sudo mode
|
||||
self.sudo().read(['website_meta_title', 'website_meta_description', 'website_meta_keywords'])
|
||||
|
||||
return qcontext
|
||||
|
||||
@api.model
|
||||
|
||||
@@ -23,9 +23,9 @@ class SeoMetadata(models.AbstractModel):
|
||||
_description = 'SEO metadata'
|
||||
|
||||
is_seo_optimized = fields.Boolean("SEO optimized", compute='_compute_is_seo_optimized')
|
||||
website_meta_title = fields.Char("Website meta title", translate=True, prefetch=True)
|
||||
website_meta_description = fields.Text("Website meta description", translate=True, prefetch=True)
|
||||
website_meta_keywords = fields.Char("Website meta keywords", translate=True, prefetch=True)
|
||||
website_meta_title = fields.Char("Website meta title", translate=True)
|
||||
website_meta_description = fields.Text("Website meta description", translate=True)
|
||||
website_meta_keywords = fields.Char("Website meta keywords", translate=True)
|
||||
website_meta_og_img = fields.Char("Website opengraph image")
|
||||
seo_name = fields.Char("Seo name", translate=True, prefetch=True)
|
||||
|
||||
|
||||
@@ -93,30 +93,30 @@ class TestWebsitePerformance(UtilPerf):
|
||||
def test_10_perf_sql_queries_page(self):
|
||||
# standard untracked website.page
|
||||
self.assertEqual(self._get_url_hot_query(self.page.url), 5)
|
||||
self.assertEqual(self._get_url_hot_query(self.page.url, cache=False), 8)
|
||||
self.assertEqual(self._get_url_hot_query(self.page.url, cache=False), 9)
|
||||
self.menu.unlink()
|
||||
self.assertEqual(self._get_url_hot_query(self.page.url), 5)
|
||||
self.assertEqual(self._get_url_hot_query(self.page.url, cache=False), 8)
|
||||
self.assertEqual(self._get_url_hot_query(self.page.url, cache=False), 9)
|
||||
|
||||
def test_15_perf_sql_queries_page(self):
|
||||
# standard tracked website.page
|
||||
self.page.track = True
|
||||
self.assertEqual(self._get_url_hot_query(self.page.url), 13)
|
||||
self.assertEqual(self._get_url_hot_query(self.page.url, cache=False), 16)
|
||||
self.assertEqual(self._get_url_hot_query(self.page.url, cache=False), 17)
|
||||
self.menu.unlink()
|
||||
self.assertEqual(self._get_url_hot_query(self.page.url), 13)
|
||||
self.assertEqual(self._get_url_hot_query(self.page.url, cache=False), 16)
|
||||
self.assertEqual(self._get_url_hot_query(self.page.url, cache=False), 17)
|
||||
|
||||
def test_20_perf_sql_queries_homepage(self):
|
||||
# homepage "/" has its own controller
|
||||
self.assertEqual(self._get_url_hot_query('/'), 12)
|
||||
self.assertEqual(self._get_url_hot_query('/', cache=False), 15)
|
||||
self.assertEqual(self._get_url_hot_query('/', cache=False), 16)
|
||||
|
||||
def test_30_perf_sql_queries_page_no_layout(self):
|
||||
# website.page with no call to layout templates
|
||||
self.page.arch = '<div>I am a blank page</div>'
|
||||
self.assertEqual(self._get_url_hot_query(self.page.url), 5)
|
||||
self.assertEqual(self._get_url_hot_query(self.page.url, cache=False), 5)
|
||||
self.assertEqual(self._get_url_hot_query(self.page.url, cache=False), 6)
|
||||
|
||||
def test_40_perf_sql_queries_page_multi_level_menu(self):
|
||||
# menu structure should not impact SQL requests
|
||||
@@ -135,7 +135,7 @@ class TestWebsitePerformance(UtilPerf):
|
||||
menu_aa.parent_id = menu_a
|
||||
|
||||
self.assertEqual(self._get_url_hot_query(self.page.url), 5)
|
||||
self.assertEqual(self._get_url_hot_query(self.page.url, cache=False), 8)
|
||||
self.assertEqual(self._get_url_hot_query(self.page.url, cache=False), 9)
|
||||
|
||||
def test_50_perf_sql_web_assets(self):
|
||||
# assets route /web/assets/..
|
||||
|
||||
@@ -13,8 +13,8 @@ class TestBlogPerformance(UtilPerf):
|
||||
self.env['website'].search([]).channel_id = False
|
||||
|
||||
def test_10_perf_sql_blog_standard_data(self):
|
||||
self.assertEqual(self._get_url_hot_query('/blog'), 25)
|
||||
self.assertEqual(self._get_url_hot_query('/blog', cache=False), 24)
|
||||
self.assertEqual(self._get_url_hot_query('/blog'), 26)
|
||||
self.assertEqual(self._get_url_hot_query('/blog', cache=False), 25)
|
||||
|
||||
def test_20_perf_sql_blog_bigger_data_scaling(self):
|
||||
BlogPost = self.env['blog.post']
|
||||
@@ -26,10 +26,10 @@ class TestBlogPerformance(UtilPerf):
|
||||
for blog_post in blog_posts:
|
||||
blog_post.tag_ids += blog_tags
|
||||
blog_tags = blog_tags[:-1]
|
||||
self.assertEqual(self._get_url_hot_query('/blog'), 25)
|
||||
self.assertEqual(self._get_url_hot_query('/blog', cache=False), 24)
|
||||
self.assertEqual(self._get_url_hot_query(blog_post[0].website_url), 29)
|
||||
self.assertEqual(self._get_url_hot_query(blog_post[0].website_url, cache=False), 28)
|
||||
self.assertEqual(self._get_url_hot_query('/blog'), 26)
|
||||
self.assertEqual(self._get_url_hot_query('/blog', cache=False), 25)
|
||||
self.assertEqual(self._get_url_hot_query(blog_post[0].website_url), 31)
|
||||
self.assertEqual(self._get_url_hot_query(blog_post[0].website_url, cache=False), 30)
|
||||
|
||||
def test_30_perf_sql_blog_bigger_data_scaling(self):
|
||||
BlogPost = self.env['blog.post']
|
||||
@@ -41,7 +41,7 @@ class TestBlogPerformance(UtilPerf):
|
||||
for blog_post in blog_posts:
|
||||
blog_post.write({'tag_ids': [[6, 0, random.choices(blog_tags.ids, k=random.randint(0, len(blog_tags)))]]})
|
||||
|
||||
self.assertLessEqual(self._get_url_hot_query('/blog'), 28)
|
||||
self.assertLessEqual(self._get_url_hot_query('/blog', cache=False), 28)
|
||||
self.assertLessEqual(self._get_url_hot_query('/blog'), 27)
|
||||
self.assertLessEqual(self._get_url_hot_query('/blog', cache=False), 26)
|
||||
self.assertLessEqual(self._get_url_hot_query(blog_post[0].website_url), 32)
|
||||
self.assertLessEqual(self._get_url_hot_query(blog_post[0].website_url, cache=False), 31)
|
||||
|
||||
Reference in New Issue
Block a user