Hooks in Odoo: Models, Views, and Controllers

Odoo is an open-source business management software that combines multiple business operations on a single platform. Its modular architecture enables firms to select and execute only the applications they require, such as CRM, Sales, Inventory, or Accounting, while being flexible and scalable. Odoo's modules are all self-contained, but they work together smoothly to give a complete solution. This modularity extends to the development framework, which allows developers to tweak the product without affecting its basic functioning.

Why Hooks Matter

As businesses expand and develop, so do their needs. To address these requirements, developers frequently have to adapt Odoo by extending or changing its default behavior. However, directly changing core code might cause problems, particularly during software updates or when integrating new modules. This is where hooks come into play. Hooks allow you to incorporate custom functionality by intercepting certain moments in the system (such as model creation, form updates, or controller actions) without modifying the main codebase. This strategy assures that the system is straightforward to upgrade and maintain, lowering the likelihood of disputes or data integrity issues.

What Are Hooks in Odoo?

Hooks in Odoo are techniques that allow developers to modify or expand the system's default behavior without changing the core code. Odoo's framework is intended to be modular and extendable, and hooks are an important aspect of that architecture. Using hooks, developers can add new functionality at key moments in the system's life cycle, such as record generation, form updating, or request handling. Hooks serve as interception points for custom code to affect how models, views, or controllers behave, allowing modification without jeopardizing system stability or making upgrades difficult.

Types of Hooks

1.Model Hooks:

Model hooks are methods that allow developers to modify how records are created, updated, or deleted in the database.

Key model hooks include:


  • create(): This method is invoked whenever a new record is created. Developers can override this function to provide custom behavior, such as setting default values, conducting validations, or initiating activities after record creation.

  • write(): This method is used to update an existing record. Overriding write() allows developers to control how data is written to the database.

  • unlink(): This method is called when records are deleted. Custom logic can be used here to prohibit record deletion under particular conditions or to initiate additional actions when a record is removed.

Example: Overriding the create() method in a custom module to assign default values or perform calculations before saving a new record.

2.View Hooks:

View hooks enable developers to interact with the Odoo user interface. These hooks are designed to respond to user actions and changes in form fields. The @api.onchange decorator is a typical view hook that is fired when the user changes the value of a field. This hook can be used to update additional fields in the form based on user input or to validate the form before it is saved.


Example: Using @api.onchange to determine a total price when a quantity or unit price field in an invoice form is changed.

3.Controller Hooks:

Controller hooks are used to change the behavior of Odoo's web controllers, which process HTTP requests for both frontend and backend processes. Overriding controller methods allows developers to apply new logic to process HTTP requests, such as altering responses, handling API calls, or expanding the capabilities of Odoo's built-in web controllers.


Example: Extending a web controller to add custom behavior for a website form submission or to process incoming requests for a third-party integration.

Common Hooks in Odoo Development


Hooks are essential for altering Odoo's behavior without modifying the core code. Below, we'll look at how to implement hooks and the most often used hooks in Odoo development for models, views, and controllers, as well as examples of how to utilize them.

Creating a Custom Module

The first step to implementing hooks in Odoo is creating a custom module. Below is a step-by-step guide for setting up a basic module:

1. Module Structure: Start by establishing a new directory for your custom module. Let’s call it custom_hooks. Inside the module directory, you need the following structure:

custom_hooks/
├── __init__.py
├── __manifest__.py
├── models/
│   └── __init__.py
│   └── custom_model.py
└── controllers/
    └── __init__.py
    └── custom_controller.py

2. Define the Manifest File: The __manifest__.py file contains the module’s metadata:

{
    'name': 'Custom Hooks Module',
    'version': '1.0',
    'depends': ['base'],
    'data': [],
    'installable': True,
    'application': True,
}

3. Initialize the Module: The __init__.py files will import the models and controllers:

from . import models
from . import controllers

Model Hooks

Odoo models describe the structure and behavior of business data. To change how records are generated, modified, or destroyed in Odoo, developers frequently override the following important methods:

1. create():

Example: Suppose we want to automatically set a default value for a field in a custom module:

from odoo import models, fields, api

class CustomModel(models.Model):
    _name = 'custom.model'

    name = fields.Char(string='Name')
    default_field = fields.Char(string='Default Field')

    @api.model
    def create(self, vals):
        # Set a default value if not provided
        vals['default_field'] = vals.get('default_field', 'Default Value')
        return super(CustomModel, self).create(vals)

2. write():

Example: You can override the write() method to log changes or enforce rules on field updates:

def write(self, vals):
   
    if 'name' in vals:
        # Log name changes
        _logger.info(f"Record {self.id} updated name from {self.name} to {vals['name']}")
    return super(CustomModel, self).write(vals)

3. unlink():

Example: Prevent deletion if a certain condition is not met:

def unlink(self):
    for record in self:
        if record.name == 'Protected':
            raise UserError('This record cannot be deleted.')
    return super(CustomModel, self).unlink()

View Hooks

@api.onchange

Odoo's view hooks enable developers to adapt or respond to changes in the user interface. The @api.onchange decorator is a popular view hook that fires when a field value in the form view changes.


Example: Let's say we want to automatically update a total price field whenever the quantity or unit price changes in an invoice form:

from odoo import models, fields, api


class InvoiceLine(models.Model):

    _name = 'invoice.line'


    quantity = fields.Integer(string='Quantity')

    unit_price = fields.Float(string='Unit Price')

    total_price = fields.Float(string='Total Price', compute='_compute_total_price')


    @api.onchange('quantity', 'unit_price')

    def _compute_total_price(self):

        for line in self:

            line.total_price = line.quantity * line.unit_price

In this example, the @api.onchange hook ensures that when the user updates the quantity or unit price, the total price is recalculated in real-time.

Controller Hooks


Extending Odoo Controllers


Odoo controllers handle HTTP routes and requests for both the backend and frontend. Developers can use hooks to extend or enhance controllers, adding their own logic to existing routes or creating new ones.


Example: Let’s extend an Odoo controller to add custom logic for processing a website form submission:

from odoo import http
from odoo.http import request

class CustomController(http.Controller):

    @http.route('/custom/form', type='http', auth="public", website=True)
    def custom_form(self, **post):
# Custom logic to handle form data
        name = post.get('name')
        email = post.get('email')
       
        # Create a new record in the 'custom.model' based on the form submission
        request.env['custom.model'].sudo().create({
            'name': name,
            'email': email,
        })
       
        # Redirect to a thank-you page
        return request.render('custom_module.thank_you_template')

In this example, we enhance Odoo's web controller to handle form submissions from the frontend, automatically producing a record in a custom model each time the form is submitted. This shows how controller hooks can change Odoo's web interface functionality.

Hooks in Odoo: Models, Views, and Controllers
Romaniia Hibliak May 1, 2025
Share this post
Tags
Archive
Sign in to leave a comment
A Detailed Review of OWL Components: Odoo’s Web Development Ecosystem