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