summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRomain Derie <rde@odoo.com>2020-03-26 18:06:32 +0000
committerRomain Derie <rde@odoo.com>2020-03-26 18:12:47 +0000
commit2c09e00a64a6f565d56c16c0b72549bc6c680b6a (patch)
treecbf257113fdf235f342c058698b648937d38f1e9
parent7ec403a1e3899a8dafae1dfc8ad623fcf8cad79f (diff)
[IMP] website: perf - prefetch menus when serving a page
If we are rendering a page, the menus will most likely be rendered as well. Note that even in a 403 case when the page is found but is not visible, the menus will also be shown on the 403 page. Fetching the menus before accessing the requested page will prefetch that page as well in one go if that page is in the menus, without any costs for the pages not in the menus. There is a tradeoff for 'non-layout' pages, which only occurs in advanced technical cases: 1. Create a page with specific extension as name suffix (page.css) in which case the page will be bootstraped accordingly, without call to layout. 2. Remove the call to layout in HTML editor or backend 3. Remove the call to submenus template in HTML editor or backend For those cases, the menus will be prefetched for no reason. Note that homepage '/' is rendered through a controller, same logic is applied there. task-2211013
-rw-r--r--addons/website/controllers/main.py4
-rw-r--r--addons/website/models/ir_http.py3
-rw-r--r--addons/website/tests/test_performance.py10
3 files changed, 11 insertions, 6 deletions
diff --git a/addons/website/controllers/main.py b/addons/website/controllers/main.py
index 8019abba5c4..df2bf628660 100644
--- a/addons/website/controllers/main.py
+++ b/addons/website/controllers/main.py
@@ -68,6 +68,9 @@ class Website(Home):
@http.route('/', type='http', auth="public", website=True, sitemap=True)
def index(self, **kw):
+ # prefetch all menus (it will prefetch website.page too)
+ top_menu = request.website.menu_id
+
homepage = request.website.homepage_id
if homepage and (homepage.sudo().is_visible or request.env.user.has_group('base.group_user')) and homepage.url != '/':
return request.env['ir.http'].reroute(homepage.url)
@@ -76,7 +79,6 @@ class Website(Home):
if website_page:
return website_page
else:
- top_menu = request.website.menu_id
first_menu = top_menu and top_menu.child_id and top_menu.child_id.filtered(lambda menu: menu.is_visible)
if first_menu and first_menu[0].url not in ('/', '', '#') and (not (first_menu[0].url.startswith(('/?', '/#', ' ')))):
return request.redirect(first_menu[0].url)
diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py
index 80ec1d9f0c7..c850a3a4e0b 100644
--- a/addons/website/models/ir_http.py
+++ b/addons/website/models/ir_http.py
@@ -239,6 +239,9 @@ class Http(models.AbstractModel):
published_domain = page_domain
# specific page first
page = request.env['website.page'].sudo().search(published_domain, order='website_id asc', limit=1)
+ if page:
+ # prefetch all menus (it will prefetch website.page too)
+ request.website.menu_id
if page and (request.website.is_publisher() or page.is_visible):
_, ext = os.path.splitext(req_page)
return request.render(page.get_view_identifier(), {
diff --git a/addons/website/tests/test_performance.py b/addons/website/tests/test_performance.py
index c257de62b88..92e1616f29a 100644
--- a/addons/website/tests/test_performance.py
+++ b/addons/website/tests/test_performance.py
@@ -77,25 +77,25 @@ 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), 14)
+ self.assertEqual(self._get_url_hot_query(self.page.url), 12)
self.menu.unlink()
self.assertEqual(self._get_url_hot_query(self.page.url), 14)
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), 22)
+ self.assertEqual(self._get_url_hot_query(self.page.url), 20)
self.menu.unlink()
self.assertEqual(self._get_url_hot_query(self.page.url), 22)
def test_20_perf_sql_queries_homepage(self):
# homepage "/" has its own controller
- self.assertEqual(self._get_url_hot_query('/'), 21)
+ self.assertEqual(self._get_url_hot_query('/'), 19)
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), 8)
+ self.assertEqual(self._get_url_hot_query(self.page.url), 10)
def test_40_perf_sql_queries_page_multi_level_menu(self):
# menu structure should not impact SQL requests
@@ -113,7 +113,7 @@ class TestWebsitePerformance(UtilPerf):
menu_bb.parent_id = menu_b
menu_aa.parent_id = menu_a
- self.assertEqual(self._get_url_hot_query(self.page.url), 14)
+ self.assertEqual(self._get_url_hot_query(self.page.url), 12)
def test_50_perf_sql_web_content(self):
# assets route /web/content/..