Decorators allow you to modify the way a method behaves. Moreover, it allows us to extend the behavior of another function, or in short, it takes in a function and adds certain functionality to it, and then returns the function.
This blog will describe method decorators in Odoo 13
The decorators in Odoo include the following:
api.depends
The function defined with this decorator will be called if any change happens in the fields specified. Moreover, the change to the field can be from ORM or changes in the form. Furthermore, if a compute function value depends on another field, then it must be specified using depends. In addition, the depends attribute can also be dotted field names such as ‘product_id.categ_id’.
balance = fields.Monetary(string='Balance', store=True, currency_field='company_currency_id',compute='_compute_balance', help=" field holding the debit - credit")
@api.depends('debit', 'credit')
def _compute_balance(self):
for line in self:
line.balance = line.debit - line.credit
As we are clear on the decorator api.depends let's now move onto the next decorator api.constraints in the next section.
api.constraints
The function with this decorator will be called on to create or write actions on the record. In addition, the function is invoked whenever the named fields of the record is modified and the validations can be done for the fields in this function. Furthermore, it can be done by raising an exception message ValidationError when the validation fails. The following is an example of the same:
from odoo.exceptions import ValidationError
class AccountCashboxLine(models.Model):
""" Cash Box Details """
_name = 'account.cashbox.line'
@api.constrains('amount', 'amount_currency')
def _check_amount_currency(self):
for line in self:
if line.amount_currency != 0 and line.amount == 0:
raise ValidationError(_('"Amount" must be specified.'))
As we are clear on the decorator api.constraints let's now move onto the next decorator api.onchange in the next section.
api.onchange
The function of this decorator will be called when the field value changes. Moreover, it supports only single field names; on the contrary, dotted names such as parent_id.field_name will not be considered. Furthermore, onchange methods are invoked on pseudo-records that contain values of the form. The following is an example of the same:
@api.onchange('partner_id')
def _onchange_partner_id(self):
values = self._onchange_partner_id_values(self.partner_id.id if self.partner_id else False)
self.update(values)
api.returns
Used to return some value when a particular method is called.
@api.returns('stock.warehouse', lambda value: value.id)
def get_warehouse(self):
""" Returns warehouse id of warehouse that contains location """
domain = [('view_location_id', 'parent_of', self.ids)]
return self.env['stock.warehouse'].search(domain, limit=1)
As we are clear on the decorator api.onchange let's now move onto the next decorator api.model in the next section.
api.model
This decorator helps in the migration of code, as it will convert old API calls to new API signatures. Moreover, you can create and write functions coded in the old API and can be easily updated using this API. In addition, this decorator can be used in methods where the self is a recordset and its model is relevant than its contents.
@api.model. Here is an example code of the same:
@api.model
def _get_default_invoice_date(self):
return fields.Date.today() if self._context.get('default_type', 'entry') in ('in_invoice', 'in_refund', 'in_receipt') else False
As we are clear on the decorator api.model let's now move onto the next decorator api.model_create_multi in the next section.
api.model_create_multi
The function defined with this decorator takes a list of dictionaries and creates multiple records. Moreover, the method can be called with a single or list of dictionaries. Here is an example code of the same:
@api.model_create_multi
def create(self, vals_list):
records = super(SurveyUserInput, self).create(vals_list)
records._check_for_failed_attempt()
return records
Can be called with
record = model.create(vals)
records = model.create([vals, ...])
As we are clear on the decorator api.model_create_multi let's now move onto the next decorator api.depends_context in the next section.
api.depends_context
This decorator takes the context dependencies of the compute method, every argument in it will be a key in the context dictionary.
The keys with special support include:
force_company: This ensures that the computed field is recomputed based on the current company or company in context.
uid: Checks the current user and superuser flag.
active_test: Takes context value of env.context or field.context.
Here is an example code of the api.depends_context:
@api.depends('country_id')
@api.depends_context('force_company')
def _compute_product_pricelist(self):
company = self.env.context.get('force_company', False)
res = self.env['product.pricelist']._get_partner_pricelist_multi(self.ids, company_id=company)
for p in self:
p.property_product_pricelist = res.get(p.id)
That's all about the api.depends_context decorator in Odoo. Moreover, it was the last Method Decorators in Odoo 13.