Odoo Compute vs Onchange Methods
Odoo offers two essential mechanisms to apply dynamic logic within
models: Compute Methods and Onchange
Methods. Both serve different purposes but are commonly
used together in business applications like quotation pricing,
inventory adjustments, or order references.
What is a Compute Method?
A compute method is used to automatically calculate the value of a
field based on one or more other fields. This value is not stored
unless explicitly declared with store=True, and it is recalculated
whenever a dependent field changes.
Example: Calculating Total Rent in a Vehicle Rental System
Let’s build a simple rental model where the total rent is calculated
based on:
- hour_rate: Rate per hour
- hours: Number of hours
from odoo import models, fields
class VehicleRental(models.Model):
_name = "vehicle.rental"
_description = "Vehicle Rental"
hour_rate = fields.Monetary(string="Hourly Rate")
hours = fields.Integer(string="Hours")
total_rent = fields.Monetary(string="Total Rent", compute="_compute_total_rent")
def _compute_total_rent(self):
for record in self:
record.total_rent = record.hour_rate * record.hours
At this point, the total rent is computed—but not automatically
updated when either field changes. To fix that, we need to add
dependencies to tell Odoo when this field should be recalculated.
Using @api.depends for Compute Fields
Odoo’s ORM depends on the @api.depends() decorator to understand
which fields affect a computed field.
from odoo import models, fields, api
class VehicleRental(models.Model):
_name = "vehicle.rental"
_description = "Vehicle Rental"
hour_rate = fields.Monetary(string="Hourly Rate")
hours = fields.Integer(string="Hours")
total_rent = fields.Monetary(string="Total Rent", compute="_compute_total_rent")
@api.depends('hour_rate', 'hours')
def _compute_total_rent(self):
for record in self:
record.total_rent = record.hour_rate * record.hours
Odoo will automatically re-compute total_rent if either hour_rate or
hours changes—without needing user interaction.
What is an Onchange Method?
The @api.onchange() method is triggered only in the form view when
the value of a specified field is changed by the user. It’s
primarily used for real-time updates in the UI, not for storing
computed values in the database.
Example: Setting Reference on Vehicle Selection
Let’s update the rental model to include a reference name that
dynamically updates when the user selects a vehicle.
from odoo import models, fields, api
class VehicleRental(models.Model):
_name = "vehicle.rental"
_description = "Vehicle Rental"
name = fields.Char(string="Reference")
vehicle_id = fields.Many2one('fleet.vehicle', string="Vehicle")
@api.onchange('vehicle_id')
def _onchange_vehicle(self):
if self.vehicle_id:
self.name = f"Rental Order for {self.vehicle_id.name}"
When a user picks a vehicle in the form view, the name field
auto-fills with a reference like “Rental Order for Toyota
Camry”. This does not store the name unless the user saves
the record.