Working with relational fields in Odoo, such as One2many, Many2many, and Many2one, often requires programmatically creating, updating, or deleting related records. Before Odoo 14, developers used cryptic tuples like (0, 0, Vals) or (4, id) to perform such operations. This method was functional but lacked clarity and was prone to errors.
With the introduction of the Command class (starting in Odoo 14 and strongly encouraged from Odoo 16 onward), developers now have a cleaner, more Pythonic, and readable way to manipulate relational fields. In this blog post, we’ll explore what the Command class is, its various types, and when to use each, along with real-world examples from an Odoo developer's perspective.
Fields of type one2many and Many2many require a specific 3-element tuple format, known as a command, to manage the relationships they represent. The first element of the tuple is an integer that identifies the type of operation (such as create, update, delete, link, or clear). The second element is either the ID of the related record (for update, delete, unlink, and link commands) or 0 (for create, clear, and set commands). The third element varies depending on the command type: it can be a dictionary of values to apply (for create and update), a list of related record IDs (for set), or 0 (for delete, unlink, link, and clear).
What is the command class
The Command class provides a structured approach to manipulate relational fields using named methods instead of magic numbers. It replaces the older tuple-based syntax.
To use this command method, you first should import the class along with the Python file
from odoo import Command
Now, we can call the command class in our function.
In Odoo 18, there are so many Command classes we can access, they are,
* command .create(vals)
* command.delete(id, vals)
* command.link(id)
* command.unlink(id)
* command.update(id)
* command.clear()
Real-life example,
1.Create()
Assume you're working on a custom module for managing sales orders, and you want to programmatically update the order_line field (a One2many relationship) on a sale- order.
sale_order.write({
'order_line': [
Command.create({
'product_id': 1,
'product_uom_qty': 2,
'price_unit': 100.0,
}),
]
})
This will create a new order line with the specified product and quantity.
2.update()
sale_order.write({
'order_line': [
Command.update(10, {
'price_unit': 150.0,
}),
]
})
Here, we are updating the order line with ID 10 and changing its price.
3.Delete()
sale_order.write({
'order_line': [
Command.delete(11),
]
})
This will completely delete the order line record from the database.
4. Link an Existing Record (Many2many)
user.write({
'groups_id': [
Command.link(14)
]
})
5. Unlink a Record
user.write({
'groups_id': [
Command.unlink(14)
]
})
6. Clear All Related Records
sale_order.write({
'order_line': [
Command.clear(),
]
})
Benefits of Using the Command Class
1. Readability: Named methods are far easier to understand than numerical tuples.
2. Maintainability: Clearer intent makes it easier for your team to modify code later.
3. Error Reduction: Typing mistakes in tuple indexes are common; Command minimizes this.
4. Forward Compatibility: As Odoo evolves, the Command class will remain the supported approach.
The Command class in Odoo 18 is a powerful and expressive way to work with relational fields. Whether you're creating new records, updating existing ones, or managing links in many-to-many fields, Command gives you the clarity and control you need. If you're still using legacy tuple syntax in your code, consider refactoring with Command, your future self (and team) will thank you!
To read more about What Are Key Mixins & Classes in Odoo 18, refer to our blog What Are Key Mixins & Classes in Odoo 18.