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