Enable Dark Mode!
relational-fields-in-odoo.jpg
By: Aneesh K

What are Relational Fields in Odoo

Technical

Relational fields in Odoo are used to link one model with another. Relational fields are important because it is a very common need that we have to create relational links between different models, for developing and implementing our business as per the needs in Odoo.
For example, in the model of Sales Order, we need to have fields that are related to the model of Products, Contacts, Salesman, Company, and many more.
In this blog, we will discuss the different types of relational fields in Odoo.
Also, the use of relational fields is the main tool that makes the integration between different models possible, which is a very important and useful feature in Odoo.
The three types of Relational fields in Odoo are:
1. Many2one field
2. One2many field
3. Many2many field

Many2one fields
A Many2one field relates the current model's record with one among the many records of the second model, called the co-model. By convention, many2one fields have the _id suffix.
You can define a Many2one field in your model as:
field_id  = fields.Many2one(‘comodel.name’, ‘Field Name’)
The value of such a field will be a record set of size 0 (no record) or 1 (a single record). If we check the database table of the model, the column corresponding to the Many2one field will be of the type integer and will contain an integer value, which is the id of the record of the co-model.
You can also easily access the fields of the related record as:
filed_id.name

For example, if we want to relate our model with the ‘product.template’ model and name the field as ‘Product’, we can define a Many2one field called ‘product_id’ as:
product_id = fields.Many2one('product.template', 'Product')
If we want to get the name of this product, which is stored as a character field called ‘name’ in the comodel, you can use: ‘product_id.name’.
Or else if you want to get the category of this product, which is defined as  ‘categ_id’, a Many2one field in the co-model, you can use: ‘product_id.categ_id’
The parameters that can be used for the field are:
a) comodel_name (str) – It is the name of the target model. It is mandatory except for related or extended fields.
b) domain – To provide a domain for the field, in order to filter the records with conditions.
c) context (dict) – To provide context to use on the client-side when handling that field.
d) ondelete (str) – To decide what to do when the referred record is deleted. The values can be: 'set null', 'restrict', 'cascade'
e) auto_join (bool) – To decide whether JOINs are generated upon search through that field (default: False)
f) delegate (bool) – If set to True fields of the target model will be accessible from the current model (corresponds to _inherits)
g) check_company (bool) – Mark the field to be verified in _check_company() function. Add a default company domain depending on the field attributes.
One2many fields
An One2many field relation is the inverse of the Many2one relation. The field relates one record of the co-model to many records of the model. The two important parameters of the field are - ‘comodel_name’, which is the name of the related model and ‘inverse_name’, which is the name of the inverse Many2one field in comodel. By convention, One2many fields have the _ids suffix.
You can define an One2many field in your model as:
field_ids  = fields.One2many(‘comodel.name’,’inverse_name’, ‘Field Name’)
The value of such a field will be the recordset of all the records in comodel such that the field inverse_name is equal to the current record.
If we check the database table of the model, we cannot find a column for the One2many field, because the data is not stored in the model’s database table. Rather the relational data is stored in the comodel’s database table under the column of corresponding inverse Many2one field. That is, the integer value in the column of the inverse Many2one field indicates the ID of our model’s record where it is related using the One2many field.
The field value will behave as a list of records, therefore we can access the data using a loop, like:
for rec in self.field_ids:
    print(rec.name)
For example, consider this field defined in the model ‘res.partner’.
sale_order_ids = fields.One2many('sale.order', 'partner_id', 'Sale Orders')
Here the sale_order_ids field is an One2many field with comodel ‘sale.order’ which has a Many2one field 'partner_id', that is related to the ‘res.partner’ model.
We cannot find a column called ‘sale_order_ids’ in the database table of ‘res.partner’. But we can see the ID of the records of ‘res.partner’ under the column ‘partner_id’ in the database table of the comodel ‘sale.order’, which are related using our One2many field.
If you want to get the name of the sale_order_ids, which is stored as a character field called ‘name’ in the comodel, you can use:
for rec in self.sale_order_ids:
    print(rec.name)
The parameters that can be used for the field are:
a) comodel_name (str) – It is the name of the target model to which we want to create the relational field.
b) inverse_name (str) – It is the name of the inverse Many2one field in comodel_name.
c) domain – To provide a domain for the field in order to filter the records with conditions.
e) context (dict) – To provide context to use on the client-side when handling that field.
f) auto_join (bool) – To decide whether JOINs are generated upon search through that field (default: False)
g) limit (int) – To provide an optional limit to use upon reading.
The attributes comodel_name and inverse_name are mandatory except in the case of related fields or field extensions.
Man2many fields
A Many2many are bidirectional multiple relationships. That is, any number of records on one side can be related to any number of records on the other side.
The important parameter of the field is - ‘comodel_name’, which is the name of the related model. By convention, Many2many fields have the _ids suffix.
You can define a Many2many field in your model as:
field_ids  = fields.Many2many(‘comodel.name’, string=‘Field Name’)
The field value will behave as a list of records, therefore we can access the data using a loop, like:
for rec in self.field_ids:
    print(rec.name)
For example, if we want to relate our model with ‘res.users’ model and name the field as ‘Users’, we can define a Many2many field called ‘user_ids’ as:
user_ids = fields.Many2many('res.users', string='Users')
Here, any number of records in the model can be related to any number of records in the comodel ‘res.users’.
The parameters that can be used for the field are:
a) comodel_name – It is the name of the target model to which we want to create the relational field.
b) relation (str) – It is an optional name of the table that stores the relation in the database
c) column1 (str) – It is an optional name of the column referring to our model’s records in the table ‘relation’.
d) column2 (str) – It is an optional name of the column referring to comodel’s records in the table ‘relation’.
Another example is the field ‘tag_ids’ defined in the model ‘sale.order’
tag_ids = fields.Many2many('crm.tag', 'sale_order_tag_rel', 'order_id', 'tag_id', string='Tags')
If we check the database table of ‘sale.order’ we cannot find a column called ‘tag_ids’. In the case of the Many2many field, a separate database table is created to store the relational data. Here in this case we can find a table called ‘sale_order_tag_rel’ in the database, having two columns ‘order_id’ and ‘tag_id’ where the corresponding ID of records are stored.
If we didn’t provide the optional attributes - ‘relation’, ‘column1’ and ‘column2’, their names are automatically generated based on the model_name and comodel_name.


If you need any assistance in odoo, we are online, please chat with us.



1
Comments

Francisco Javier Guillén Ramírez

Hi, I have tried to use a related Many2one field, take this example that I came across there: deudor_id = fields.Many2one('res.partner', 'Deudor', readonly=True, required=True, states={'draft': [('readonly', False)]}) fiador_id = fields.Many2one('res.partner', related='deudor_id.fiador_id', string='Fiador', store=True) But when I restart Odoo and update the module it gives me this error: KeyError: 'fiador_id' - - The example is an Odoo 8 and I am trying to use it in Odoo 14. What is he doing wrong? I have looked for documentation everywhere but none of them clarifies how to use it in Odoo 14. Best regards... Francisco Javier Guillén Ramírez

29/09/2021

-

11:34PM



Leave a comment



whatsapp_icon
location

Calicut

Cybrosys Technologies Pvt. Ltd.
Neospace, Kinfra Techno Park
Kakkancherry, Calicut
Kerala, India - 673635

location

Kochi

Cybrosys Technologies Pvt. Ltd.
1st Floor, Thapasya Building,
Infopark, Kakkanad,
Kochi, India - 682030.

location

Bangalore

Cybrosys Techno Solutions
The Estate, 8th Floor,
Dickenson Road,
Bangalore, India - 560042

Send Us A Message