[IMP] website_sale: overhead on every page

website_sale adds a call to sale_get_order to ~every website page (in
order to validate & display the shopping cart).

Before this change, this calls get_pricelist_available() and triggers
two different computations of property_product_pricelist on every page
even for a public user with no cart / SO. This, in turn, generates ~20
queries and adds 20ms (total) / 10ms (sql) to ~every page load.

Fix: early return if the user doesn't have an SO (either in session or
in DB) and we're not in a case where we want to force one.

Loading "/" with just website_sale installed on a new DB,

- before: 53 queries, 31ms ±5 (sql), 75ms ±5 (all)
- after: 32 queries, 21ms ±1 (sql), 53ms ±3 (all)

closes odoo/odoo#32492

Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
This commit is contained in:
Xavier Morel
2019-04-08 11:40:08 +00:00
parent be8af5dc9c
commit 265926f971
+65 -65
View File
@@ -239,27 +239,32 @@ class Website(models.Model):
self.ensure_one()
partner = self.env.user.partner_id
sale_order_id = request.session.get('sale_order_id')
if not sale_order_id:
if not sale_order_id and not self.env.user._is_public():
last_order = partner.last_website_so_id
available_pricelists = self.get_pricelist_available()
# Do not reload the cart of this user last visit if the cart uses a pricelist no longer available.
sale_order_id = last_order.pricelist_id in available_pricelists and last_order.id
if last_order:
available_pricelists = self.get_pricelist_available()
# Do not reload the cart of this user last visit if the cart uses a pricelist no longer available.
sale_order_id = last_order.pricelist_id in available_pricelists and last_order.id
pricelist_id = request.session.get('website_sale_current_pl') or self.get_current_pricelist().id
# Test validity of the sale_order_id
sale_order = self.env['sale.order'].sudo().browse(sale_order_id).exists() if sale_order_id else None
if not (sale_order or force_create or code):
request.session['sale_order_id'] = None
return self.env['sale.order']
if self.env['product.pricelist'].browse(force_pricelist).exists():
pricelist_id = force_pricelist
request.session['website_sale_current_pl'] = pricelist_id
update_pricelist = True
else:
pricelist_id = request.session.get('website_sale_current_pl') or self.get_current_pricelist().id
if not self._context.get('pricelist'):
self = self.with_context(pricelist=pricelist_id)
# Test validity of the sale_order_id
sale_order = self.env['sale.order'].sudo().browse(sale_order_id).exists() if sale_order_id else None
# create so if needed
if not sale_order and (force_create or code):
# cart creation was requested (either explicitly or to configure a promo code)
if not sale_order:
# TODO cache partner_id session
pricelist = self.env['product.pricelist'].browse(pricelist_id).sudo()
so_data = self._prepare_sale_order_values(partner, pricelist)
@@ -280,70 +285,65 @@ class Website(models.Model):
request.session['sale_order_id'] = sale_order.id
if sale_order:
# case when user emptied the cart
if not request.session.get('sale_order_id'):
request.session['sale_order_id'] = sale_order.id
# case when user emptied the cart
if not request.session.get('sale_order_id'):
request.session['sale_order_id'] = sale_order.id
# check for change of pricelist with a coupon
pricelist_id = pricelist_id or partner.property_product_pricelist.id
# check for change of pricelist with a coupon
pricelist_id = pricelist_id or partner.property_product_pricelist.id
# check for change of partner_id ie after signup
if sale_order.partner_id.id != partner.id and request.website.partner_id.id != partner.id:
flag_pricelist = False
if pricelist_id != sale_order.pricelist_id.id:
flag_pricelist = True
fiscal_position = sale_order.fiscal_position_id.id
# check for change of partner_id ie after signup
if sale_order.partner_id.id != partner.id and request.website.partner_id.id != partner.id:
flag_pricelist = False
if pricelist_id != sale_order.pricelist_id.id:
flag_pricelist = True
fiscal_position = sale_order.fiscal_position_id.id
# change the partner, and trigger the onchange
sale_order.write({'partner_id': partner.id})
sale_order.onchange_partner_id()
sale_order.write({'partner_invoice_id': partner.id})
sale_order.onchange_partner_shipping_id() # fiscal position
sale_order['payment_term_id'] = self.sale_get_payment_term(partner)
# change the partner, and trigger the onchange
sale_order.write({'partner_id': partner.id})
sale_order.onchange_partner_id()
sale_order.write({'partner_invoice_id': partner.id})
sale_order.onchange_partner_shipping_id() # fiscal position
sale_order['payment_term_id'] = self.sale_get_payment_term(partner)
# check the pricelist : update it if the pricelist is not the 'forced' one
values = {}
if sale_order.pricelist_id:
if sale_order.pricelist_id.id != pricelist_id:
values['pricelist_id'] = pricelist_id
update_pricelist = True
# if fiscal position, update the order lines taxes
if sale_order.fiscal_position_id:
sale_order._compute_tax_id()
# if values, then make the SO update
if values:
sale_order.write(values)
# check if the fiscal position has changed with the partner_id update
recent_fiscal_position = sale_order.fiscal_position_id.id
if flag_pricelist or recent_fiscal_position != fiscal_position:
# check the pricelist : update it if the pricelist is not the 'forced' one
values = {}
if sale_order.pricelist_id:
if sale_order.pricelist_id.id != pricelist_id:
values['pricelist_id'] = pricelist_id
update_pricelist = True
if code and code != sale_order.pricelist_id.code:
code_pricelist = self.env['product.pricelist'].sudo().search([('code', '=', code)], limit=1)
if code_pricelist:
pricelist_id = code_pricelist.id
update_pricelist = True
elif code is not None and sale_order.pricelist_id.code:
# code is not None when user removes code and click on "Apply"
pricelist_id = partner.property_product_pricelist.id
# if fiscal position, update the order lines taxes
if sale_order.fiscal_position_id:
sale_order._compute_tax_id()
# if values, then make the SO update
if values:
sale_order.write(values)
# check if the fiscal position has changed with the partner_id update
recent_fiscal_position = sale_order.fiscal_position_id.id
if flag_pricelist or recent_fiscal_position != fiscal_position:
update_pricelist = True
# update the pricelist
if update_pricelist:
request.session['website_sale_current_pl'] = pricelist_id
values = {'pricelist_id': pricelist_id}
sale_order.write(values)
for line in sale_order.order_line:
if line.exists():
sale_order._cart_update(product_id=line.product_id.id, line_id=line.id, add_qty=0)
if code and code != sale_order.pricelist_id.code:
code_pricelist = self.env['product.pricelist'].sudo().search([('code', '=', code)], limit=1)
if code_pricelist:
pricelist_id = code_pricelist.id
update_pricelist = True
elif code is not None and sale_order.pricelist_id.code:
# code is not None when user removes code and click on "Apply"
pricelist_id = partner.property_product_pricelist.id
update_pricelist = True
else:
request.session['sale_order_id'] = None
return self.env['sale.order']
# update the pricelist
if update_pricelist:
request.session['website_sale_current_pl'] = pricelist_id
values = {'pricelist_id': pricelist_id}
sale_order.write(values)
for line in sale_order.order_line:
if line.exists():
sale_order._cart_update(product_id=line.product_id.id, line_id=line.id, add_qty=0)
return sale_order