12

Recently odoo (formerly OpenERP) V8 has been released. In new API method decorators are introduced. in models.py methods needs to be decorated with @api.one or @api.multi.

Referring odoo documentation i can not determine the exact use. Can anybody explain in detail.

Thanks.

BomberMan
  • 1,094
  • 3
  • 13
  • 33

3 Answers3

17

Generally both decoarators are used to decorate a record-style method where 'self' contains recordset(s). Let me explain in brief when to use @api.one and @api.multi:

1. @api.one:

  • Decorate a record-style method where 'self' is expected to be a singleton instance.

  • The decorated method automatically loops on records (i.e, for each record in recordset it calls the method), and makes a list with the results.

  • In case the method is decorated with @returns, it concatenates the resulting instances. Such a method:

    @api.one def method(self, args): return self.name

may be called in both record and traditional styles, like::

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

names = model.method(cr, uid, ids, args, context=context)
  • Each time 'self' is redefined as current record.

2. @api.multi:

  • Decorate a record-style method where 'self' is a recordset. The method typically defines an operation on records. Such a method:

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

may be called in both record and traditional styles, like::

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

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

When to use:

  1. If you are using @api.one, the returned value is in a list. This is not always supported by the web client, e.g. on button action methods. In that case, you should use @api.multi to decorate your method, and probably call self.ensure_one() in the method definition.

  2. It is always better use @api.multi with self.ensure_one() instead of @api.one to avoid the side effect in return values.

BomberMan
  • 1,094
  • 3
  • 13
  • 33
  • As long as I see the method decorators allow to specify semantic information of how you are processing the records inside. Regarding the point "when to use api.multi". Is this criteria based on the webclient support ? This problems can not be resolved via api.return in all the cases? I see that way we sacrifice semantic information that can be useful for the ORM to make optimizations and decide the proper calls. I think that It is like use more and more SQL statements when the ORM doesn't support some operation instead of improving it. – yucer Mar 04 '16 at 11:01
  • 1
    @BomberMan Thanks for the detailed explanation! That solved my mystery :) I was wondering why I received a list from my method :) – IstaLibera May 31 '17 at 08:49
  • 1
    Good answer! Just want to add that @api.one is deprecated since v9.0 (https://www.odoo.com/documentation/10.0/reference/orm.html#module-odoo.api) – Fractalf Oct 25 '17 at 08:12
5

@api.one:

This decorator loops automatically on Records of RecordSet for you. Self is redefined as current record:

@api.one
def func(self):
    self.name = 'xyz'

@api.multi:

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

@api.multi
def func(self):
    len(self)

For the detailed description of all API you can refer this Link

bud-e
  • 1,511
  • 1
  • 20
  • 31
1
@api.model #When the record data/self is not as relevant. Sometimes also used with old API calls.
def model_text(self):
    return "this text does not rely on self"

@api.multi #Normally followed by a loop on self because self may contain multiple records
def set_field(self):
    for r in self:
        r.abc = r.a + r.b

@api.one #The api will do a loop and call the method for each record. Not preferred because of potential problems with returns to web clients
def set_field(self):
    self.abc = self.a + self.b
Palza
  • 642
  • 5
  • 12
  • Please try to avoid just dumping code as an answer and try to explain what it does and why. Your code might not be obvious for people who do not have the relevant coding experience. – Frits Sep 12 '16 at 06:31