Controllers are often used in conjunction with models and views to create web applications in Odoo, allowing developers to define the behavior of custom pages and extend the functionality of the system.
Here, we discuss how to override an existing controller.
1. Create a Separate Directory:
Start by creating a dedicated directory for the controller. Within this directory, include both the Python file associated with the controller and the initialization file. Then, initialize the Python file within the init file.
2. Define Subclass and Select Function:
To override a controller, define the existing function in a subclass. Identify the class to which this controller belongs. develop a subclass and customize the targeted function. Here, we demonstrate overriding the website_sale Carousel function.
from odoo.addons.website_sale.controllers.main import WebsiteSale
from odoo.http import request
class ProductsRecentlyViewes(WebsiteSale):
"""Returns list of recently viewed products according to current user."""
Here, I am creating a new class with the name ProductRecentlyViewes with the subclass of WebsiteSale. Here, we can see importing some libraries. When overriding the existing class, we have to create a subclass of the existing functions in a class, so we need to import the full path of the overriding class.
from Odoo.addons.website_sale.controllers.main import WebsiteSale
Syntax of importing the full path of the inherited class.
from <path_to_existing_controller> import <ClassName>
* Modify the Overridden Function:
Make necessary changes in the selected overriding function. In this example, the Carousel's maximum display limit is modified from 12 to 10 products.
class ProductsRecentlyViewes(WebsiteSale):
"""Returns list of recently viewed products according to current user."""
def _get_products_latest_viewed(self):
"""Returns list of recently viewed products according to current user."""
max_number_of_product_for_carousel = 10
visitor = request.env['website.visitor']._get_visitor_from_request()
if visitor:
excluded_products = request.website.sale_get_order().mapped(
'order_line.product_id.id')
products = request.env['website.track'].sudo().read_group(
[('visitor_id', '=', visitor.id),
('product_id', '!=', False),
('product_id.website_published', '=', True),
('product_id', 'not in', excluded_products)],
['product_id', 'visit_datetime:max'], ['product_id'],
limit=max_number_of_product_for_carousel,
orderby='visit_datetime DESC')
products_ids = [product['product_id'][0] for product in
products]
if products_ids:
viewed_products = request.env[
'product.product'].with_context(
display_default_code=False).browse(products_ids)
FieldMonetary = request.env['ir.qweb.field.monetary']
monetary_options = {
'display_currency': request.website.get_current_pricelist().currency_id,
}
rating = request.website.viewref(
'website_sale.product_comment').active
res = {'products': []}
for product in viewed_products:
combination_info = product._get_combination_info_variant()
res_product = product.read(['id', 'name', 'website_url'])[
0]
res_product.update(combination_info)
res_product['price'] = FieldMonetary.value_to_html(
res_product['price'], monetary_options)
if rating:
res_product['rating'] = request.env[
"ir.ui.view"]._render_template(
'portal_rating.rating_widget_stars_static',
values={
'rating_avg': product.rating_avg,
'rating_count': product.rating_count,
})
res['products'].append(res_product)
return res
return {}
* Override Function Using qcontext:
When rendering the template, make modifications or use the same parameters through qcontext or **kwargs. If additional values need to be passed or returned, use qcontext or update it.
* Handle Route Definition:
Be cautious when overriding a controller with a route. Ensure the inherited subclass includes the route definition to avoid issues. Make necessary modifications once the route is stated in the inherited subclass.
* Example Using qcontext:
Here's an example using qcontext to override a function and modify the product name:
@http.route([
'/shop',
'/shop/page/<int:page>', '/shop/category/<model("product.public.category"):category>',
'/shop/category/<model("product.public.category"):category>/page/<int:page>',
], type='http', auth="public", website=True, sitemap=sitemap_shop)
def shop(self, page=0, category=None, search='', min_price=0.0, max_price=0.0, ppg=False, **post):
res = super().shop(self, page=0, category=None,
search='', min_price=0.0,
max_price=0.0, ppg=False,
**post)
product = res.qcontext.get(products)
for rec in product:
if rec.id == 9:
rec.name = 'Normal Desk'
return res
Two Main Approaches to Override an Existing Function in Odoo 17
When it comes to overriding an existing function in Odoo 17, developers typically employ one of two primary methods. It's essential to understand the distinctions between these approaches
a) Function Overriding:
In this method, the existing function from the parent class is transferred to the class being inherited. Subsequently, modifications are made as necessary to ensure that the new function fully replaces the previous one. This approach is ideal when a complete overhaul or customization of the function's behavior is required.
b) Supering a Function:
The "supering" method is employed when developers can inherit all the features and characteristics of a function from the parent class by making minimal changes. Instead of completely replacing the function, developers utilize the super() function to access and extend the functionality of the parent class's function. This approach is suitable when minor adjustments or additions are needed, preserving the core functionality inherited from the parent class.
In summary, this article covers the process of overriding functions and existing controllers in Odoo 17.