Method Decorators In Odoo 8
Decorator simply decorates a method according to our needs. In odoo 7 we use cursor, uid, context and ids for defining all method here we can’t use such parameters, here we use self as the parameter when defining a method with certain method decorators.
This decorator's are passed the parameters explicitly to the method. Which provide a smooth way to write functions and avoid complications.
This manages the elements in two different API styles, namely:
- traditional styles.
- record styles.
In the “traditional” style, parameters like the db cursor, uid, context dictionary and record ids (usually written as cr, uid, context, ids) are passed explicitly to all methods.
In the “record” style, those parameters are hidden into model instances.
Recordsets is an Ordered collection of records of the same model, to replace browse_records, browse_list and browse_null.
Record is simply the database record which contains id, model, context, forces create, and we can write to database by this following way.
Example:
record = self
record.state = “State”
This will update the state in caches and call the write function to perform write action in database.
Decorators in odoo:
- @api.one
- @api.multi
- @api.model
- @api.depends
- @api.returns
- @api.onchange
- @api.constrains
- @api.noguess
@api.one
It is specific for one record and can not be used for multiple records. It automatically loop over record in the recordset. Self is redefined as current record.
Example
@api.one
def afun(self):
self.company_name = ‘Test’
self.company_code = ‘test123’
From this example, we will get an idea how will the function affects our records. This function will automatically writes company name and company code field of each records with ‘Test’ and ’test123’.
@api.multi
It can used for multiple record, so we can loop through it. Here Self contains recordset, so that we need a for loop for iterating through each record.
Example:
@api.multi
def afun(self):
self.company_name = ‘Test’
self.company_code = ‘test123’
If we are writing the function like this, we will get an error.
So rewrite the example :
@api.multi
def afun(self):
for record in self:
record.company_name = ‘Test’
record.company_code = ‘test123’
@api.model
This decorator will convert old API calls to decorated function to new API signature.
Example:
created_id = fields.Many2one('res.users', default=_default_created_user, string='Created by')
@api.model
def _default_created_user(self):
uid = self._uid
return uid
This will return the current user.
@api.depends
This decorator is specifically used for "fields.function" in odoo. The decorator function works only if any of the fields specified in the decorator is changed in the form.
Dependencies can be dotted paths when using sub-fields
For example:
@api.depends('partner_id.street')
def _get_street(self):
for record in self:
for line in record.partner_id:
record.street = line.street
If compute uses the values of other fields, it should be specified in depends().
-
compute is simply the fields.function in odoo 7, here the functional fields are replaced with compute, by assigning the function name to compute parameter, see the example given below
Computed field are not stored by default, they are computed the function and return the value, same as in odoo 7 here we use store = True to store the computed value to database.
Example
salary = fields.Float(compute='_get_salary', string='Salary', readonly=True)
@api.one
@api.depends('ta', 'da', 'hra', 'ba')
def _get_salary(self):
ta = (self.ta/100)*self.ba
da = (self.da/100)*self.ba
hra = (self.hra/100)*self.ba
self.salary = ta + da + hra + self.ba
From this example, we will get an idea how will the function affects database without store parameter. This function will not store calculated values without specifying the parameter store as True
@api.returns
This decorator is used for decorating the returned value from a method. It guarantees the unity of returned value from a method. It will return a RecordSet of specified model. If an old API function calls a new API function it will automatically convert it into a list of ids.
Example:
@api.returns('self')
def _get_return(self):
return self
@api.onchange
In odoo 7 we use onchange method, in which an onchange attribute is written in the corresponding field tag in xml and in py file, here we use a decorator. Which will avoid the onchange attribute in xml file. The working of this decorator is same as the working of onchange method in odoo 7, the fields are written as the parameter of the function.
Example
@api.onchange('date_of_birth','age')
def onchange_age_calculation(self ):
if not self.date_of_birth:
self.age = 0
else:
today_date = datetime.now().year
date_split = self.date_of_birth.split('-',1)
birth_year = date_split[0]
self.age = today_date -int(birth_year)
From this example , we will get an idea how will the function affects our records. This function will automatically writes age field when changing the value of date_of_birth field in form view.
1.Onchange with Warning
Example:
@api.onchange('date_of_birth','age')
def onchange_age_calculation(self ):
birth_date = self.date_of_birth
now_date = str(datetime.now().date())
if birth_date == now_date:
return {
'warning': {
'title': _('Warning!'),
'message': _('You are not a valid user.'),
},
'value': {
'date_of_birth': 1
}
}
2. Onchange with Domain
Example:
@api.onchange('partner_id')
def _onchange_partner_id(self):
contact_ids = self.env['res.partner'].search([('parent_id','=',self.partner_id.id), ('type','=','site_address')])
if contact_ids:
self.site_id = contact_ids[0]
else:
self.site_id = self.partner_id.id
return {'domain': {'site_id': [('parent_id', '=', self.partner_id.id )]}}
@api.constrains
This decorator will ensure that decorated function will be called on create, write, unlink operation. It will act as a constraint checker. This will especially used for warning messages and validation.
Example:
1. Warning with appropriate message.
@api.one
@api.constrains('roll_number')
def _check_roll_number(self):
if self.roll_number and type(self.roll_number) != int’:
raise Warning(_('Roll number must be numeric.'))
2. Validation with appropriate message.
@api.one
@api.constrains(‘password’, 'confim_password’)
def _check_password(self):
if self.password == self.confim_password:
raise ValidationError("Fields Password and Confirm password must be same")
@api.noguess
This decorator prevent new API decorators to alter the output of a method.
From this we get an idea about the decorator and how to use, where to use. I hope that this will be helpful to write methods using decorator in odoo 8.
Thank you.