Odoo has different types of fields like Character, Integer, Boolean, etc. Odoo also has relational fields which help to create relationships between different models. A reference field will help to create a dynamic relationship in a model, Which means we can select the model dynamically to create the relation. In Many2one, One2many, and Many2many fields we can pre-define the target model in which the relationship needs to be created. For example, in a Sale Order, if we create a Many2one field for customers, it will only create a relation between these two models, here we pre-define the target model that is customers.
In the case of the reference field first, we can select the target model and then select the record. For example, In the Customer model, I need to add the field 'Document Source'. In this, for some customers, I may have to add a Purchase Order as a document source, for some other customers need to add Sale Order as the source. Sometimes I may need to add an Invoice as the source. In this case, I can define a reference field for this. I have to first choose the model (Purchase, Sale, or Invoice) and then select the record.
We can see a simple example of a reference field from Settings >> Technical >> Menu Items.
If we try to create a Menu Item from here, we have to choose an Action for this menu. This Action field is a Reference Field. Because first, we have to select the action model, ie select whether it is an ir.actions.the report, ir.actions.server, ir.actions.act_window, etc. After selecting that, we can select the particular action of the selected model.
After selecting the model it will show another field to choose the records in the selected model.
After saving, it will show as a single field (only the record) like a Many2one field.
We can check how we can define the reference fields. For this, I'm taking the above 'Document Source field in Contacts' as an example.
source_document = fields.Reference (selection = [('sale.order', 'Sale Order'),
('purchase.order', 'Purchase Order'),
('account.move', 'Invoice')],
string = "Source Document")
Here, we can choose a Sale Order, Purchase Order, or Invoice for customers from the same field.
Customer with Sale ref.
Customer with Purchase ref.
Customer with Invoice ref.
Also, we can choose the values ??for the selection from a function. Remember that I have to select records from all modules in a field. Then use
source_document = fields.Reference (selection = '_ select_target_model', string = "Source Document")
@ api.model
def _select_target_model (self):
models = self.env ['ir.model']. search ([])
return [(model.model, model.name) for model in models]
It will show all available models to select.
A reference field will store in the database as <model_name>, id.
Eg: sale.order, 10
We can access the reference fields like we access a Many2one filed.
Now we can check how we can write data into a reference field.
For example in this 'Source Document' field, I want the Last Sale Order of the customer as reference,
def _selection_target_model (self):
model = self.env ['ir.model']. search ([('model', '=', 'sale.order')])
return [(model.model, model.name) ] source_document = fields.Reference (selection = '_ selection_target_model', string = "Source Document", compute = "_ compute_sale_order", inverse = "_ set_sale_order") def _compute_sale_order (self): order = self.env ['sale.order'] .search ([('partner_id', '=', self.id)], order = 'id desc', limit = 1) for rec in self: if order:
rec.source_document = '% s,% s'% ('sale.order', order.id)
else: rec.source_document = False def _set_sale_order (self): order = self.env ['sale.order']. search ([('partner_id', '=', self.id)], order = 'id desc', limit = 1) for rec in self: if rec.source_document: order.id = rec.source_document.id In the above code, it will select the last sale order of the partner if he has an order, defining an 'inverse' function to make the compute field editable, so we can also select the orders. We can write data in to a reference field like, self.field_name = '% s,% s'% (' model.
Eg: self.order_ref = '% s,% s'% (purchase.order', order.id)