Welcome to this in-depth tutorial on Advanced Odoo Relational Fields. If you are looking to elevate your Odoo development skills, understanding how to effectively use relational fields is absolutely crucial. Consequently, this guide will walk you through the core concepts, practical applications, and step-by-step implementations of these powerful Odoo ORM (Object-Relational Mapping) components. Furthermore, we will explore how Odoo’s ORM leverages these fields to build robust and interconnected applications, making your development process more efficient and your applications more powerful. By mastering Advanced Odoo Relational Fields, you can significantly improve data integrity and create more intuitive user experiences within your Odoo modules.
Understanding Odoo’s ORM and Relational Data
Before we dive into the specifics of different relational field types, it’s important to grasp the foundational concepts of Odoo’s ORM and why relational data is so pivotal in application development.
What is an ORM in Odoo?
Firstly, Odoo’s ORM is a powerful programming technique that provides an object-oriented layer between your Python code and the underlying relational database (typically PostgreSQL). Instead of writing raw SQL queries, you interact with database tables and records as Python objects and their attributes. This abstraction simplifies database operations, enhances code readability, and improves maintainability. Moreover, the ORM handles the translation of these object-oriented operations into SQL queries automatically. Therefore, developers can focus more on the business logic rather than the intricacies of database management. The ORM is a cornerstone of Odoo development, enabling rapid application development and ensuring a consistent data access layer.
Why Relational Fields Matter for Odoo Developers
Relational fields are the backbone of creating meaningful connections between different data models in Odoo. For instance, in a typical business application, a sales order needs to be linked to a customer, products need to belong to categories, and employees might be associated with departments. These connections are established using relational fields.
Specifically, these fields allow you to:
- Define Relationships: They explicitly define how different pieces of information are related, such as one-to-many, many-to-one, or many-to-many relationships.
- Ensure Data Integrity: By setting up proper relations, you can enforce rules like preventing the deletion of a customer if they have existing sales orders, thereby maintaining referential integrity. The VTT script highlights that these fields “guarantee our referential integrity between models.”
- Simplify Data Retrieval: The ORM uses these relationships to easily fetch related data. For example, when you access a sales order object, you can effortlessly retrieve the associated customer’s details.
- Improve User Interface: Odoo’s web client intelligently uses relational fields to provide user-friendly widgets, like dropdowns for selecting a related record or list views for displaying multiple related records.
Understanding and correctly implementing Advanced Odoo Relational Fields is therefore essential for building complex, data-driven applications in Odoo.
Mastering Many2one Fields in Odoo
The Many2one field is one of the most frequently used relational fields in Odoo. It establishes a “many-to-one” relationship, meaning many records in the current model can be linked to a single record in another model. Think of it as a foreign key in traditional database terms.
Defining Many2one Relationships
Essentially, a Many2one field in an Odoo model creates a column in the model’s database table that stores the ID of a record from another (target) model. This allows multiple records in the source model to point to one specific record in the target model.
For example:
- Many sales orders can be linked to one customer.
- Many products can belong to one product category.
- Many employees can report to one manager.
Practical Examples of Many2one
Let’s consider a practical scenario: a custom Odoo module for managing a library. In this module, we’ll have a library.book model for books and an library.author model for authors. A book is typically written by one primary author (for simplicity in this example, though co-authorship can be handled with Many2many).
- Scenario: Each book in the
library.bookmodel needs to be associated with one author from thelibrary.authormodel. - Implementation: You would add a
Many2onefield namedauthor_idto thelibrary.bookmodel, targeting thelibrary.authormodel.
This setup ensures that when you create or view a book record, you can select or see its associated author.
Step-by-Step: Creating a Many2one Field
Now, let’s see how to define a Many2one field in your Odoo Python model.
- Define your models:
First, ensure you have both models defined. For our library example: models/library_author.py from - Example
odoo import models, fields
class LibraryAuthor(models.Model):
_name = 'library.author'
_description = 'Library Author'
name = fields.Char(string='Author Name', required=True)
# Other fields like biography, etc.# models/library_book.py
from odoo import models, fields
class LibraryBook(models.Model):
_name = 'library.book'
_description = 'Library Book'
name = fields.Char(string='Title', required=True)
isbn = fields.Char(string='ISBN')
# Defining the Many2one field
author_id = fields.Many2one(
comodel_name='library.author', # The target model
string='Author', # Label for the field in UI
required=True, # Makes the field mandatory
ondelete='restrict' # Behavior when the related author is deleted
)
# Other fields like publication_date, number_of_pages, etc.
- Explanation of Parameters:
comodel_name: This is a crucial parameter. It specifies the name of the target model to which this field relates (e.g.,'library.author').string: This defines the label that will be displayed for this field in the Odoo user interface (e.g.,'Author').required=True: This optional parameter makes the field mandatory. Users will not be able to save a book record without selecting an author.ondelete: This parameter dictates what happens if the referenced record (the author, in this case) is deleted. Common values include:'cascade': If the author is deleted, all books by that author will also be deleted. Use with caution.'set null': If the author is deleted, theauthor_idfield in the related book records will be set toNULL. This requires the field not to berequired=Trueat the database level.'restrict': Prevents the deletion of an author if there are any books linked to them. This is often a good default for maintaining data integrity.'set default': Sets the field to its default value if the related record is deleted.
Impact on Database and User Interface
Database Level:
When Odoo processes this model definition, it creates a column in the library_book table (e.g., author_id) which will store an integer (the ID of the author from the library.author table). Additionally, Odoo might create a foreign key constraint depending on the ondelete behavior and database settings.
User Interface (UI) Level:
In the Odoo UI, the author_id field will typically render as a dropdown list (if there are few records) or a searchable selection field. This allows users to easily pick an existing author or even create a new one on the fly (if configured). Consequently, this provides a seamless experience for managing these Advanced Odoo Relational Fields.
Exploring One2many Fields: The Inverse Relationship
Next, we explore One2many fields. A One2many field is the inverse of a Many2one relationship. It allows a single record in the current model to be linked to multiple records in another model. Importantly, a One2many field doesn’t create a new column in the current model’s database table. Instead, it relies on a Many2one field in the other model that points back to the current model.
Understanding One2many Connections
Think of it this way: if a library.book has a Many2one field pointing to library.author, then the library.author model can have a One2many field that lists all the books associated with that author. The One2many field provides a “view” from the “one” side of the relationship to the “many” side.
Real-world Scenarios for One2many
Continuing our library example:
- Scenario: An author in the
library.authormodel can have written multiple books, which are recorded in thelibrary.bookmodel. We want to see all books by a specific author directly on the author’s form. - Implementation: You would add a
One2manyfield namedbook_idsto thelibrary.authormodel. This field will reference theauthor_id(theMany2onefield) in thelibrary.bookmodel.
Other examples include:
- A customer (
res.partner) can have multiple sales orders (sale.order). - A product category (
product.category) can contain multiple products (product.template).
Step-by-Step: Implementing a One2many Field
Let’s add the One2many field to our library.author model.
- Ensure the
Many2onefield exists:
We already haveauthor_id = fields.Many2one('library.author', ...)in thelibrary.bookmodel. This is the crucial link. - Define the
One2manyfield in the target model (library.author):
# models/library_author.py
from odoo import models, fields
class LibraryAuthor(models.Model):
_name = 'library.author'
_description = 'Library Author'
name = fields.Char(string='Author Name', required=True)
# Defining the One2many field
book_ids = fields.One2many(
comodel_name='library.book', # The model on the "many" side
inverse_name='author_id', # The Many2one field in 'library.book' that links back
string='Books by this Author' # Label for the UI
)
# Other fields
- Explanation of Parameters:
comodel_name: This specifies the name of the model on the “many” side of the relationship (e.g.,'library.book').inverse_name: This is a critical parameter. It’s the name of theMany2onefield in thecomodel_name(i.e., inlibrary.book) that links back to the current model (library.author). In our case, it’s'author_id'.string: The label for the field in the Odoo UI (e.g.,'Books by this Author').
Visualizing One2many in Odoo Views
Database Level:
As mentioned, a One2many field does not create a new column in the library_author table. It’s a virtual field in terms of database structure for the current model; it queries the library.book table using the author_id foreign key.
User Interface (UI) Level:
In the Odoo UI, a One2many field is typically displayed as an embedded list or kanban view within the form of the parent record. For instance, on an author’s form, you would see a section listing all their books. Users can often add, edit, or delete related records (books, in this case) directly from this embedded view, making it a very powerful feature for managing related data. This interactive display is a key benefit when working with Advanced Odoo Relational Fields.
Unlocking Many2many Fields for Complex Relations
Finally, let’s discuss Many2many fields. These fields are used to represent “many-to-many” relationships, where multiple records in one model can be related to multiple records in another model.
The Concept of Many2many Links
Consider a scenario where a book can have multiple tags (e.g., “Fiction,” “Sci-Fi,” “Mystery”), and a tag can be applied to multiple books. This is a classic many-to-many relationship.
To implement this, Odoo typically creates an intermediary (or relation) table in the database. This table will have two columns, each being a foreign key pointing to one of the related models. Each row in this intermediary table represents a single link between a record from the first model and a record from the second model.
When to Use Many2many Fields
Many2many fields are ideal for situations like:
- Products and Tags: A product can have many tags, and a tag can be associated with many products.
- Students and Courses: A student can enroll in multiple courses, and a course can have multiple students.
- Users and Groups: A user can belong to multiple security groups, and a group can contain multiple users (this is a built-in Odoo example).
Let’s enhance our library module. Suppose we want to categorize books using tags.
- Scenario: A book can have multiple tags (e.g., “Programming,” “Odoo,” “Python”). A tag can be applied to many different books.
- Implementation: We’ll create a
library.book.tagmodel and then add aMany2manyfield tolibrary.bookto link to these tags.
Step-by-Step: Building a Many2many Field
- Define the related model (if it doesn’t exist):
First, let’s create thelibrary.book.tagmodel.
# models/library_book_tag.py
from odoo import models, fields
class LibraryBookTag(models.Model):
_name = 'library.book.tag'
_description = 'Library Book Tag'
name = fields.Char(string='Tag Name', required=True)
# You might add a color index or other properties for tags
- Define the
Many2manyfield in one of the models (e.g.,library.book):
# models/library_book.py
from odoo import models, fields
class LibraryBook(models.Model):
_name = 'library.book'
_description = 'Library Book'
name = fields.Char(string='Title', required=True)
isbn = fields.Char(string='ISBN')
author_id = fields.Many2one(
comodel_name='library.author',
string='Author',
required=True,
ondelete='restrict'
)
# Defining the Many2many field
tag_ids = fields.Many2many(
comodel_name='library.book.tag', # The other model in the M2M relationship
relation='library_book_tag_rel', # Optional: Name of the intermediary table
column1='book_id', # Optional: Column name in rel table for current model's ID
column2='tag_id', # Optional: Column name in rel table for other model's ID
string='Tags' # Label for the UI
)
# Other fields
- Explanation of Parameters:
comodel_name: The name of the other model involved in the many-to-many relationship (e.g.,'library.book.tag').relation(optional): The name of the intermediary database table that Odoo will create to store the relationships. If you don’t provide this, Odoo generates a name automatically (e.g.,model1_model2_rel). It’s good practice to define it for clarity, especially for Advanced Odoo Relational Fields.column1(optional): The name of the column in therelationtable that will store the IDs from the current model (library.book). If not specified, Odoo usescurrent_model_name_id.column2(optional): The name of the column in therelationtable that will store the IDs from thecomodel_name(library.book.tag). If not specified, Odoo usescomodel_name_id.string: The label for the field in the Odoo UI.
How Odoo Manages Many2many Tables
Database Level:
When you define a Many2many field, Odoo automatically creates the intermediary table (e.g., library_book_tag_rel) if it doesn’t exist. This table will have at least two columns (e.g., book_id and tag_id), both acting as foreign keys to their respective tables. Each row in this table signifies an association. For example, if a book with ID 5 is tagged with tags having IDs 10 and 12, the library_book_tag_rel table would have two rows: (5, 10) and (5, 12).
User Interface (UI) Level:
In the Odoo UI, Many2many fields are typically rendered as a list of selectable tags or a multi-select field. Users can easily add or remove associations. For our tag_ids field, Odoo would display a widget allowing users to select multiple tags for a book from the available library.book.tag records.
Advanced Tips for Odoo Relational Fields
Now that you understand the basics of Many2one, One2many, and Many2many fields, let’s touch upon some advanced aspects and best practices.
Using ondelete for Data Integrity
As briefly mentioned with Many2one fields, the ondelete attribute is crucial for maintaining data integrity.
'cascade': Deletes related records. Use this very carefully as it can lead to data loss if not intended. For example, if deleting a sales order should also delete its lines,cascadewould be appropriate for theOne2manyfield linking orders to lines (though this is often handled by Odoo’s default forsale.order.line).'set null': Sets the foreign key toNULL. This is useful if the relationship is optional. The database column must allowNULLvalues.'restrict': Prevents deletion if related records exist. This is often the safest option to avoid accidental data loss and orphaned records.'set default': Sets the foreign key to its default value.
Choosing the correct ondelete behavior is a key part of designing robust Advanced Odoo Relational Fields.
Domain Filters on Relational Fields
You can apply a domain attribute to relational fields to restrict the choices available to the user in the UI. A domain is a list of triplets that specifies filtering conditions.
Example: On a Many2one field for selecting a “Project Manager” (who is a user), you might want to only show users who are part of the “Project Management” group.
project_manager_id = fields.Many2one(
'res.users',
string='Project Manager',
domain="[('groups_id', 'in', [ref('my_module.group_project_manager')])]"
)
This makes the selection process more targeted and user-friendly.
Context with Relational Fields
The context attribute can be used with relational fields to pass default values or other contextual information when creating new related records from the UI or when opening the related record’s form.
Example: When creating a new contact from a sales order, you might want to automatically set the contact type to ‘customer’.
partner_id = fields.Many2one(
'res.partner',
string='Customer',
context="{'default_customer_rank': 1}"
# Assuming 'customer_rank' > 0 means it's a customer
)
Performance Considerations with Advanced Odoo Relational Fields
While relational fields are powerful, they can impact performance if not used judiciously, especially with large datasets.
- Fetching Related Data: Accessing relational fields can trigger additional database queries. Odoo’s ORM is quite optimized, but be mindful of deeply nested accesses in loops (the N+1 problem).
One2manyandMany2manyfields: These can load many related records. Use them wisely in list views or ensure proper pagination and filtering.- Indexing: Ensure that foreign key columns (created by
Many2onefields and inMany2manyrelation tables) are properly indexed in the database for faster joins and lookups. Odoo usually handles this, but for custom or complex scenarios, verification might be needed. You can use theindex=Trueattribute on fields, although Odoo often creates indexes automatically for relational fields.
For further reading on Odoo’s ORM and field types, you can refer to the official Odoo ORM API documentation.
Conclusion
Mastering Advanced Odoo Relational Fields – Many2one, One2many, and Many2many – is fundamental to becoming a proficient Odoo developer. These fields are not just about linking tables; they are about modeling complex business logic, ensuring data integrity, and creating intuitive user interfaces. By carefully choosing the right type of relational field and configuring its attributes like comodel_name, inverse_name, ondelete, domain, and context, you can build powerful, scalable, and maintainable Odoo applications.
Furthermore, remember that the ORM handles much of the underlying SQL complexity, allowing you to work at a higher level of abstraction. Therefore, continue to practice implementing these fields in various scenarios, and you’ll find yourself building more sophisticated Odoo modules with greater ease and confidence. Happy coding!
Discover more from teguhteja.id
Subscribe to get the latest posts sent to your email.


Pingback: Odoo write vs update: 7 Powerful Reasons to Choose Write