Enable Dark Mode!
overview-of-inheriting-controllers-in-odoo-19.jpg
By: Vishnu P

Overview of Inheriting Controllers in Odoo 19

Technical Odoo 19 Odoo Enterprises Odoo Community

Odoo’s web framework is very flexible and lets developers change or extend almost any part of the system. One useful feature is controller inheritance, which allows you to update or add new behavior to existing controllers without modifying the main Odoo code.

In this blog, we’ll look at what controllers are, why we inherit them, and how to do it in Odoo 19 with a few simple examples.

What Are Odoo Controllers?

In Odoo, controllers are Python classes that handle web requests.

They define the routes (URLs) and decide what happens when someone visits them, for example, showing a web page, sending JSON data, or redirecting to another page.

Every controller in Odoo is a subclass of odoo.http.Controller.

Example:

from odoo import httpfrom odoo.http import requestclass ExampleController(http.Controller):   @http.route('/hello', type='http', auth='public', website=True)   def hello_world(self, **kwargs):       return "Hello, Odoo!"

When a user visits /hello, Odoo runs this method and returns the response.

Why Inherit Controllers?

If you’ve worked with Odoo for a while, you probably know that editing the core files is never a great idea. It makes upgrades painful and can break things later.

A better way is to inherit controllers—that’s basically extending what’s already there instead of rewriting it.

So, why bother inheriting a controller at all? Well, a few good reasons come to mind:

  • Add something extra: Maybe the existing route works fine, but you want it to do a little more.
  • Change behavior: You can make a route respond differently without touching the main code.
  • Add new routes: Sometimes you just need a new endpoint but still want to reuse the original logic.
  • Keep your code clean: Leaving Odoo’s core untouched means future updates are way less painful.

How to Inherit a Controller

So, inheriting a controller in Odoo isn’t really complicated. You don’t have to rewrite much—just make a new class that picks up from the one you want to extend.

For example, the website_sale module builds on top of WebsiteForm from the website module. That’s how it handles form submissions for eCommerce stuff.

from odoo.addons.website.controllers.form import WebsiteFormclass WebsiteSaleForm(WebsiteForm):   # Custom logic goes here   pass

And that’s it—your new controller now has everything the WebsiteForm one had. You can use its routes and methods or just override what you need.

Example: Extending an Existing Method

Let’s say you want to tweak the _get_country_related_render_values method from WebsiteForm.

No need to rewrite the whole thing. Just override it in your own class and call the original method using super().

from odoo.addons.website.controllers.form import WebsiteFormfrom odoo.http import requestclass WebsiteSaleForm(WebsiteForm):   def _get_country_related_render_values(self, country, **kwargs):       values = super()._get_country_related_render_values(country, **kwargs)       # Add custom logic       values['states'] = values['states'].filtered(lambda s: s.country_id == country)       return values

Here, we use super() to call the original method and then update the values it returns.

This way, your custom code stays consistent with Odoo’s original design and behavior.

Example: Adding a New Route

You can also add new routes in your inherited controller.

For example, the WebsiteSaleForm controller includes a route that handles sales order submissions.

from odoo.addons.website.controllers.form import WebsiteFormfrom odoo.http import request, routeimport jsonfrom odoo.exceptions import ValidationErrorfrom odoo.addons.base.models.ir_qweb_fields import nl2br_encloseclass WebsiteSaleForm(WebsiteForm):   @route('/website/form/shop.sale.order', type='http', auth="public", methods=['POST'], website=True)   def website_form_saleorder(self, **kwargs):       model_record = request.env.ref('sale.model_sale_order').sudo()       try:           data = self.extract_data(model_record, kwargs)       except ValidationError as e:           return json.dumps({'error_fields': e.args[0]})       order_sudo = request.cart       if not order_sudo:           return json.dumps({'error': "No order found; please add a product to your cart."})       if data['record']:           order_sudo.write(data['record'])       if data['custom']:           order_sudo._message_log(               body=nl2br_enclose(data['custom'], 'p'),               message_type='comment',           )       if data['attachments']:           self.insert_attachment(model_record, order_sudo.id, data['attachments'])       return json.dumps({'id': order_sudo.id})

So, this route basically handles a POST request. It grabs the form data, updates the sales order, and sends a JSON reply back to the browser. Simple and clean—nothing complicated is going on there.

Real Examples from Odoo

If you’ve ever looked through Odoo’s source code (and I highly recommend doing it once), you’ll notice controller inheritance is used everywhere. It’s not just something for custom modules—even Odoo’s own apps rely on it a lot.

Here are a few quick examples you’ll find in the codebase:

  • WebsiteSaleForm – extends WebsiteForm to manage online sales.
  • WebsiteHrRecruitment – inherits WebsiteForm to handle job applications.
  • WebsiteNewsletterForm – reuses WebsiteForm for newsletter subscriptions.
  • ContactController – extends WebsiteForm for contact form submissions.

Controller inheritance might not sound exciting at first, but once you start building real modules, you’ll see how powerful it is.

It lets you plug into existing logic without messing with Odoo’s core code—which saves you a lot of headaches later when you upgrade.

Personally, I try to use inheritance whenever possible. It keeps my code cleaner, easier to maintain, and way less likely to break during updates.

Even as Odoo 19 keeps evolving, this approach still feels like one of the smartest ways to build flexible, reusable web features.

To read more about What are the Different Types of Inheritance in Odoo 18, refer to our blog What are the Different Types of Inheritance in Odoo 18.


If you need any assistance in odoo, we are online, please chat with us.



0
Comments



Leave a comment



whatsapp_icon
location

Calicut

Cybrosys Technologies Pvt. Ltd.
Neospace, Kinfra Techno Park
Kakkancherry, Calicut
Kerala, India - 673635

location

Kochi

Cybrosys Technologies Pvt. Ltd.
1st Floor, Thapasya Building,
Infopark, Kakkanad,
Kochi, India - 682030.

location

Bangalore

Cybrosys Techno Solutions
The Estate, 8th Floor,
Dickenson Road,
Bangalore, India - 560042

Send Us A Message