In many real-world business applications, it's common to need data
from one model to be visible in another — without duplicating it.
Odoo provides a clean and powerful way to achieve this using related
fields and reference fields.
Related Fields
Related fields allow you to fetch and display a value from a field in
a related model, typically linked by a Many2one relationship. This
is useful when you want to show, for example, the partner's name or
email directly in your custom model without re-entering that
information.
Basic Usage Example:
partner_id = fields.Many2one('res.partner', string='Partner')
partner_name = fields.Char(string='Partner Name', related='partner_id.name')
By default, related fields are:
- Read-only: The field cannot be modified by the user.
- Not stored in the database: The field value is computed
dynamically and not saved in the database.
- Not copied when duplicating a record: The field value
will not be carried over when the record is duplicated.
To store the related field in the database — which improves
performance for sorting and searching — you can use the store=True
attribute:
partner_id = fields.Many2one('res.partner', string='Partner')
partner_name = fields.Char(string='Partner Name', related='partner_id.name', store=True)
This is especially helpful when you’re frequently filtering or
grouping based on the related field in views.
Reference Fields
Reference fields in Odoo let you dynamically select a record from
multiple models within a single field. Unlike standard relationships
(Many2one, One2many), which point to a fixed model, reference fields
provide flexibility by letting the user choose the model and then
record from that model.
reference = fields.Reference(
selection=[
('sale.order', 'Sale Order'),
('purchase.order', 'Purchase Order')
],
string="Reference Document"
)
In this example, the field allows users to link either a Sale Order
or Purchase Order.
Dynamic Model Selection from a Method:
reference = fields.Reference(
selection='get_model_options',
string="Reference"
)
@api.model
def get_model_options(self):
models = self.env['ir.model'].search([])
return [(model.model, model.name) for model in models]
This way, the field dynamically populates the list of available
models using a function. Just remember: the returned value must be a
list of tuples, where each tuple is (model_name, display_label).