An API(Application Programming Interface), is a set of subroutine definitions, protocols, and tools for building application software. In general terms, it's a set of clearly defined methods of communication between various software components.
Below are some key differences between the old and new APIs :
Values of an environment (cursor, user id and context) are passed explicitly to methods instead.
Record data (ids) are passed explicitly to methods, and possibly not passed at all.
Methods tend to work on lists of ids instead of recordsets.
A decorator, is nothing but just a callable that takes a function as an argument and returns a replacement of function. New decorators are doing a job as a mapper around the new API. The decorator are also mandatory as webclient and HTTP controller are not compliant with new API. API namespace decorators will detect signature using variable name and decide to match old signature or not.
There are two different types of API styles as follows :
TRADITIONAL STYLE : In this style, parameters like the database cursor, user id, context dictionary and record ids (usually denoted as 'cr', 'uid', 'context', 'ids') are passed explicitly to all methods.
RECORD STYLE : In this style, those parameters are hidden into model instances, which gives it a more object-oriented feel.
The decorator's which is used to decorate the record-style method :
@api.one (One-by-one or “autoloop” decorator ) : The @api.one is specific for one record and can not be used for multiple records. It automatically loops on records of a recordset for you. Decorate a record-style method where 'self' is expected to be a singleton instance.
@api.one def method(self, args): return self.name
@api.multi : The @api.multi is for multiple records, where you can loop through it etc. It will be the current recordset without the iteration. Decorate a record-style method where 'self' is a recordset.
@api.multi def method(self,args):
@api.returns (Methods that returns a recordset instead of ids) : Return a decorator for methods that return instances of 'model'. The decorator adapts the method output to the api style: 'id', 'ids' or 'False' for the traditional style, and recordset for the record style.
@api.model @api.returns('res.partner') def find_res_partner(self, arg): ... # return some record
Note : The decorated method must satisfy that convention
Those decorators are automatically inherited: a method that overrides a decorated existing method will be decorated with the same '@returns(model)'.
@api.model : The API with this decorator not use ids and no recordset operation done in method. Decorate a record-style method where self is a recordset, but its contents is not relevant, only the model is.
@api.model def method(self,args): … # recs = model.browse(cr, uid, ids, context) recs.method(args) model.method(cr, uid, args, context=context)
Note: No 'ids' are passed to the method in the traditional style.
@api.constrains : This decorator will ensure that decorated function will be called on create, write, unlink operation. If a constraint is met the function should raise a openerp.exceptions.Warning with appropriate message.
@api.one @api.constrains('name', 'description') def _check_field_description(self): if self.name == self.description: raiseValidationError("Field name and description have to be different!")
@api.depends(Computed Field) : This will return a decorator that specifies the field dependencies of a "compute" method (for new-style function fields). Each argument must be a string that consists in a dot-separated sequence of field names:
partner_name = fields.Char(compute='_compute_partner_name') @api.one @api.depends('partner_id.name', 'partner_id.is_company') def _compute_partner_name(self): if self.partner_id.is_company: self.partner_name = (self.partner_id.name or "").upper() else: self.partner_name = self.partner_id.name
One may also pass a single function as argument. In that case, the dependencies are given by calling the function with the field's model.
@api.onchange : This decorator will trigger the call to the decorated function if any of the fields specified in the decorator is changed in the form.
@api.onchange('partner_id') def _onchange_res_partner(self): self.message = "Dear %s" % (self.partner_id.name or "")
In the form views where the field appears, the method will be called when one of the given fields is modified. The method is invoked on a pseudo-record that contains the values present in the form. Field assignments on that record are automatically sent back to the client.
@api.noguess : This decorator prevent new API decorators to alter the output of a method.
The Decorator's which is used to decorate the traditional-style method :
@api.cr_uid_context : Decorate a traditional-style method that takes 'cr', 'uid', 'context' as parameters. Such a method may be called in both record and traditional styles.
@api.cr_uid_id_context : Decorate a traditional-style method that takes 'cr', 'uid', 'id', 'context' as parameters.
@api.cr_uid_ids_context : Decorate a traditional-style method that takes 'cr', 'uid', 'ids', 'context' as parameters.
The Decorator's which is used to decorate a method that supports the old-style API only :
@api.v7 : Decorate a method that supports the old-style api only. A new-style api may be provided by redefining a method with the same name and decorated with :func:'~.v8' :
@api.v7 def method(self, cr, uid, ids, context=None): ... @api.v8 def method(self): …
Note : The wrapper method uses the docstring of the first method.
@api.v8 : Decorate a method that supports the new-style api only. An old-style api may be provided by redefining a method with the same name and decorated with :func:'~.v7' :
@api.v8 def method(self): ... @api.v7 def method(self, cr, uid, ids, context=None): …
Note : The wrapper method uses the docstring of the first method.