Commonly Used Method Decorators in Odoo ERP
@api.One
Method decorator @api.one is used when you need to know the content of the record. This decorator is especially useful when you want to do some process to the record. Function with this decorator can use self keyword to get the record's values.
@api.Multi
This @api.multi decorator used for the exact same as @api.one. The only difference is that function using @api.multi decorator will have multiple records contained within self keyword. Therefore unlike @api.one, we need to iterate self in order to get the records' values.
@api.Depends
Decorator @api.depends is useful when we want a function to automatically run to return a value. This method decorator requires string arguments in the shape of the record's field names (separated by comma). This method decorator also requires a computed field defined with the function name.
Functions under @api.depends will be triggered when any fields defined on the arguments has been changed by back-end or front-end operation. Functions under this decorator will be run in real-time.
@api.Onchange
Similar to @api.depends, this method decorator also runs automatically with field changes as its trigger but the function under @api.onchange doesn't have to return any value.
Functions under @api.onchange will not be triggered without front-end operation. This means that any changes happened to the trigger fields in the back-end or via database query will not trigger the function.
@api.Constrains
Method decorator @api.constrains have some similarity to @api.depends and @api.onchange. This method decorator also requires trigger fields. The difference is, this function is (usually) used for validating values and raising exceptions.
Functions under @api.constrains will be triggered once the changes to any trigger fields are committed.
@api.Model
Method decorator @api.model is used to run the function directly from the model class and does not require a record to call the function. This decorator is usefull for running function from scheduled actions or action servers or even other models.
Comprehensive Examples of Using Method Decorator in Odoo
Consider that we have 2 models for registering devices that any person owns.
class DeviceRegistration(models.Model):
_name = "device.registration"
_description = "Device Registration"
reference = fields.Char()
first_name = fields.Char()
middle_name = fields.Char()
last_name = fields.Char()
full_name = fields.Char()
device_ids = fields.One2many("device", "registration_id")
device_count = fields.Integer(compute="_calculate_device_count", store=True)
class Device(models.Model):
_name = "device"
_description = "Devices"
_rec_name = "device_type"
registration_id = fields.Many2one("device.registration", ondelete="cascade")
device_type = fields.Selection([
('phone', 'Phone'),
('tablet', 'Tablet'),
('laptop', 'Laptop')
])
serial_number = fields.Char()
Now for the reference field, we want to automatically format it using the pre-defined prefix.
class DeviceRegistration(models.Model):
...
@api.model
def create(self, values):
record = super(DeviceRegistration, self).create(values)
record.reference = "DEVREG/%s" % record.id
return record
In the above code, we are overriding the create method which uses @api.model decorator. Using the function above, whenever we create a new record from Device Registration form, we will also update the reference field.
class DeviceRegistration(models.Model):
...
device_ids = fields.One2many("device", "registration_id")
device_count = fields.Integer(compute="_calculate_device_count", store=True)
@api.multi
@api.depends("device_ids")
def _calculate_device_count(self):
for record in self:
record.device_count = len(rec.device_ids)
Now when we are using @api.depends decorator, like we have covered above we will need a trigger field which in the above code is the device_ids field. So whenever device_ids field changes (e.g., added new device or removed a device), the function will run and compute the value for device_count.
Worth to mention that device_count field has a compute argument in its field definition. This compute argument defines what function is responsible to calculate the value (yes, the function must also fill the value to the compute field). One function under @api.depends decorator can be applied for multiple fields.
class DeviceRegistration(models.Model):
...
@api.one
@api.onchange("first_name", "middle_name", "last_name")
def _define_full_name(self):
full_name = []
if self.first_name:
full_name.append(self.first_name)
if self.middle_name:
full_name.append(self.middle_name)
if self.last_name:
full_name.append(self.last_name)
self.full_name = full_name
Now we are going through @api.onchange decorator which looks similar to @api.depends. However as we have mentioned before, this function will only run if the user changes the trigger fields (in this case either first_name, middle_name or last_name) using the Odoo interface.
Notice how in this example we are not using @api.multi instead we are using @api.one. This is why we can get the record's values by using self keyword directly while in @api.multi we need to iterate self.
class DeviceRegistration(models.Model):
...
@api.multi
@api.constrains("device_count")
def _validate_device_count(self):
for record in self:
if record.device_count > 3:
raise exceptions.UserError("One person must not have more than 3 devices registered.")
Now lastly, we have @api.constrains which we use to validate some rules whenever the trigger fields are updated. Here, whenever the Device Registration record is updated and the device_count field is changed, it will trigger this function and validate our rules which is the user can't have more than 3 devices.
If you have any other concerns, questions or even need other tutorial related to Odoo, please comment down below and we’ll get back to you real soon!