What is the difference between @ api.one, @ api.multi and @ api.model?

I am confused regarding @api.one , @api.multi and @api.model in Odoo.

What are the differences between the three and what are their use cases?

+8
source share
4 answers

api.one intended to be used when the method is called for only one record. This ensures that there are no multiple entries when calling the method with the api.one decorator api.one . Suppose you have an entry partner = res.partner(1,) . This is only one entry, and there is a method, for example (in res.partner ):

 @api.one def get_name(self): return self.name #self here means one record 

call it like this:

 partner.get_name() 

But if there are more records, for example partners = res.partner(1, 2,)

calling this will cause a warning saying that you can only call it for one record. For several records, api.multi used, where self is a set of records, and it can be repeated for all records. For instance:

 @api.multi def get_partner_names(self): names = [] for rec in self: names.append(rec.name) return ', '.join(names) 

And api.model is considered used when you need to do something with the model itself and do not need to modify / check some exact records / records of the model. For example, there may be a method that returns some meta-information about the structure of the model or some auxiliary methods, etc. The documentation also says that this API is good to use when moving from the old API, since it politely converts the code to the new API. Also, in my experience, if you need a method to return something, the model decorator is suitable for this. api.one returns an empty list, so this may lead to unexpected behavior when using the api.one on method, when it should return something.

A bit more info: http://odoo-new-api-guide-line.readthedocs.org/en/latest/decorator.html

+5
source

api.one

This decorator automatically loops over RecordSet for you. Self is redefined as the current record:

 @api.one ## here you will get singleton object in self def name(self): self.name = 'admin' 

@ api.multi

Self will be the current RecordSet without iteration. This is the default behavior:

 @api.multi ## here you will get multi objects in self def name(self): print len(self) for obj in self: obj.name = 'Admin' 

@ api.model

This decorator converts old API calls into a decorated function into a new API signature. This allows you to be polite when porting code.

 @api.model def name(self): pass 

Method decorators should be defined according to your methods, if you want to return a dictionary from a method, then your method should contain @api.multi .

Refer New API Guide

+1
source
  • The difference between one, several, and a model

In fact, you can call the @api.one method with a RecordSet containing multiple entries. The only difference is that with @api.one the write loop will be executed outside the function that you define, and as a self decorator will pass each record to the RecordSet one at a time.

As an example, let's define two functions in our example.model model:

 @api.one print_self_one(self): print self @api.multi print_self_multi(self): print self 

And call them like this: odoo shell :

 model = env['example.model'] record_set = model.browse(1,2) print "record set: " + record_set print "using @api.one:" record_set.print_self_one() print "using @api.multi:" record_set.print_self_multi() 

Will return:

 record set: example.model(1,2) using @api.one: example.model(1) example.model(2) using @api.multi: example.model(1,2) 

Thus, the following two are equivalent:

 @api.one _compute_name(self): self.name = "Default Name" @api.multi print_self_multi(self): for record in self: record.name = "Default Name" 

even if thery is called with a larger record in the recordset.

On the other hand, you are not using a decorator, then it cannot be called more (or less) than one record, or it will complain and probably stop with an error.

@api.model is a completely different story: you should use this decorator only if you expect it to be called with an empty recordset.

  • When to use

If you expect a non-empty RecordSet as an input value, then in many cases you can use both @api.one and @api.multi , this is just a matter of personal preference. I personally prefer to use @api.one whenever possible because I find the code much cleaner this way (also for calculation methods and onchange, the Odoo source usually uses @api.one ).

There are a few cases where you can use @api.multi , though:

  • If you not only want to loop records, but also want to do something only once:

     @api.multi print_self_multi(self): print "this will only be printed once" for record in self: print "this will be printed len(record_set) times" 
  • If the return value is important. A function decorated with @api.one will always return a list (a list of return values ​​in your function as an iteration). However, in some cases, especially when interacting with the graphical interface, you will have to return the dictionary (for example, with a warning). In these cases, you will have to switch from @api.multi .

+1
source

@ api.multi

Decorate a post style method, where self is a set of posts. The method automatically determines the operation on records. Such a method ::

 @api.multi def method(self, args): ... 

can be called in both traditional and ordinary styles:

 recs = model.browse(cr, uid, ids, context) recs.method(args) model.method(cr, uid, ids, args, context=context) 

@ api.model

Decorate the style of the recording style, where self is a set of records, but its contents do not matter, only the model. Such a method ::

 @api.model def method(self, args): ... 

can be called in both traditional and ordinary styles:

 recs = model.browse(cr, uid, ids, context) recs.method(args) model.method(cr, uid, args, context=context) 

You can find the base code for these decorators in the file: odoo / api.py

0
source

Source: https://habr.com/ru/post/989935/


All Articles