
Computed fields in Odoo are powerful tools for automating dynamic values based on other fields. However, their default read-only behavior can limit flexibility when users need to edit these fields. This guide explores how to use inverse functions to make computed fields editable while maintaining data consistency. Whether you’re an Odoo developer or a business user, this blog will help you unlock bidirectional field synchronization in Odoo 18.
What Are Computed Fields?
Computed fields dynamically calculate values using Python logic instead of storing them directly in the database. For example, a total_price
field might depend on quantity
and unit_price
13. Here’s a basic example:
total = fields.Float(compute='_compute_total')
@api.depends('quantity', 'unit_price')
def _compute_total(self):
for record in self:
record.total = record.quantity * record.unit_price
By default, computed fields are read-only, as their values are derived from other fields
Why Use Inverse Functions?
Inverse functions bridge the gap between computed fields and user input. They allow users to edit a computed field and propagate changes back to its dependencies. For instance:
- If a user edits a
total
field, an inverse function can adjustquantity
orunit_price
to maintain consistency 1, 3. - A
capital_letter
field computed fromsmall_letter
can inversely updatesmall_letter
when edited 2, 10. - Without inverse functions, computed fields remain static and uneditable, limiting real-world usability 4, 8
Step-by-Step Implementation:
- Define the Compute Method:
Start by declaring a computed field withcompute
and dependencies
from odoo import models, fields, api
class SaleOrder(models.Model):
_inherit = 'sale.order'
total_amount = fields.Float(
string='Total Amount',
compute='_compute_total_amount',
inverse='_inverse_total_amount',
store=True # Required for inverse to work :cite[5]:cite[10]
)
@api.depends('order_line.price', 'order_line.quantity')
def _compute_total_amount(self):
for order in self:
order.total_amount = sum(
line.price * line.quantity
for line in order.order_line
)
2. Add the Inverse Function:
The inverse method reverses the computation. For example, updating line prices when total_amount
changes:
def _inverse_total_amount(self):
for order in self:
if order.total_amount and order.order_line:
avg_price = order.total_amount / len(order.order_line)
for line in order.order_line:
line.price = avg_price / line.quantity
Here, editing total_amount
redistributes the value across order lines 3, 9.
3. Enable Editing with inverse
and store=True
:
inverse
: Links the field to the inverse method.store=True
: Stores the computed value in the database, enabling edits 51, 1.
Real-World Use Cases
- Bidirectional Synchronization
Example: Synchronize small_letter
and capital_letter
fields
capital_letter = fields.Char(
compute='_compute_capital',
inverse='_inverse_capital'
)
@api.depends('small_letter')
def _compute_capital(self):
for rec in self:
rec.capital_letter = rec.small_letter.upper()
def _inverse_capital(self):
for rec in self:
rec.small_letter = rec.capital_letter.lower()
Editing either field updates the other 2, 10.
2. Adjusting Related Models:
For related fields (e.g., partner_id.street
), an inverse function can update the linked model:
street = fields.Char(
related='partner_id.street',
inverse='_set_street'
)
def _set_street(self):
for rec in self:
rec.partner_id.street = rec.street
This ensures changes cascade to the partner model 5
Best Practices for Inverse Functions:
- Use
store=True
: Ensures the computed value is stored and editable - Define Clear Dependencies: Use
@api.depends
to trigger recomputations accurately - Avoid Overcomplication: Keep inverse logic simple to prevent performance issues
- Test Edge Cases: Handle zero divisions (e.g.,
if order.total_amount
) to avoid errors
Common Pitfalls:
- Missing
store=True
: Inverse functions won’t trigger without it - Circular Dependencies: Ensure compute and inverse methods don’t create infinite loops
- Performance Overheads: Stored computed fields can slow down large datasets; optimize dependencies