How to Implement @onchange vs @compute with inverse in Odoo?
✅ Purpose & Concept
Feature | @onchange | @compute (with @inverse) |
Triggered When | Field changes in UI (form view only) | Any relevant field changes in DB (backend + UI) |
Stores Value? | No (unless explicitly written) | Yes (if store=True) |
Bidirectional? | One-way (UI to logic) | Yes (both compute and inverse) |
Runs In | Client side | Server side (always) |
Used In Views? | Yes | Yes |
📌 Real Use Case: Set Discount Based on Product
@onchange Example
class SaleOrderLine(models.Model):
_inherit = 'sale.order.line'
@api.onchange('product_id')
def _onchange_product_id(self):
if self.product_id and self.product_id.list_price > 1000:
self.discount = 10
- When you choose a product, if its price exceeds 1000, a 10% discount will be automatically applied.
- Only works in form view during manual data entry.
- Does not trigger in batch creation or server-side operations like imports, APIs.
@compute with @inverse Example
class SaleOrderLine(models.Model):
_inherit = 'sale.order.line'
price_tax = fields.Float(compute='_compute_price_tax', inverse='_inverse_price_tax', store=True)
@api.depends('price_unit', 'tax_id')
def _compute_price_tax(self):
for line in self:
tax = line.price_unit * 0.18 if line.tax_id else 0.0
line.price_tax = tax
def _inverse_price_tax(self):
for line in self:
if line.tax_id:
line.price_unit = line.price_tax / 0.18
- Automatically calculates tax from price and stores it.
- Also allows you to set the tax manually, and it will update price_unit accordingly using the inverse method.
- Useful for data consistency, import/export, and automations.
⚙️ When to Use What?
Situation | Use @onchange | Use @compute + @inverse |
Field logic only needed in UI | ✅ Yes | ❌ Not necessary |
Field must be updated on record change | ❌ No | ✅ Yes |
Bi-directional calculation needed | ❌ No | ✅ Yes (compute + inverse) |
Works during create/update/import | ❌ No | ✅ Yes |
Temporary field logic (not stored) | ✅ Yes | ❌ Only if compute is not stored |
✅ Summary Table
Decorator | Direction | Stores Data? | Works in UI | Works in Backend | Bidirectional |
@onchange | UI → Server | No | ✅ Yes | ❌ No | ❌ No |
@compute only | Dependencies → Field | Yes/No | ✅ Yes | ✅ Yes | ❌ No |
@compute + inverse | Field ↔ Logic | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes |