How to Implement @api.onchange vs @api.depends in Odoo?


✅ Core Difference


Feature

@api.onchange

@api.depends

Purpose

Trigger logic when a field changes in UI

Recalculate a computed field when dependencies change

Execution Context

Client-side only (form view)

Server-side (ORM, UI, batch, imports, API, etc.)

Field Storage

Doesn’t affect stored fields unless manually written

Used with @compute, which can be stored or not

Usage Scenario

Interactive UI feedback (set values, warnings)

Auto-updated computed fields



📌 Real Use Case: Product-Based Discount


Using @api.onchange

@api.onchange('product_id')

def _onchange_product_id(self):

    if self.product_id and self.product_id.list_price > 1000:

        self.discount = 10


  • Triggered only when the product is changed in the form view.
  • Ideal for quick UI updates (e.g., applying a discount).


Using @api.depends with @compute


discount = fields.Float(compute='_compute_discount', store=True)


@api.depends('product_id')

def _compute_discount(self):

    for line in self:

        line.discount = 10 if line.product_id.list_price > 1000 else 0


  • Automatically computed when the product_id changes.
  • Works on all levels: UI, server, API, scheduled jobs, import, etc.


⚙️ When to Use What?


Use Case

Use @api.onchange

Use @api.depends

Form view interaction (set fields, warnings)

✅ Yes

❌ No

Dynamic computed field (stored or not)

❌ No

✅ Yes

Runs during data import / cron / API

❌ No

✅ Yes

Temporary visual feedback

✅ Yes

❌ No

Server-side data consistency

❌ No

✅ Yes



⚠️ Important Notes


  • @api.onchange does not persist unless explicitly written via self.field = value.
  • @api.depends automatically recalculates and is part of the ORM lifecycle.
  • Avoid mixing both on the same logic unless there's a specific reason.


✅ Summary Table

Decorator

Trigger Context

Works in Backend

Works in UI

Suitable For

Stores Field?

@api.onchange

UI only

❌ No

✅ Yes

Form feedback, quick set

❌ No (manual)

@api.depends

ORM full stack

✅ Yes

✅ Yes

Auto-calculating fields

✅ Yes/No