Odoo @api.one、@api.multi和@api.model之间有什么区别?

Odoo @api.one、@api.multi和@api.model之间有什么区别?,odoo,odoo-8,Odoo,Odoo 8,我对Odoo中的@api.one、@api.multi和@api.model感到困惑 三者之间的区别是什么?它们的用例是什么?api.one 此装饰器会自动为您在记录集的记录上循环。Self被重新定义为当前记录: @api.one ## here you will get singleton object in self def name(self): self.name = ’admin’ @api.multi Self将是当前记录集,无需迭代。这是默认行为: @api.mult

我对Odoo中的
@api.one
@api.multi
@api.model
感到困惑


三者之间的区别是什么?它们的用例是什么?

api.one

此装饰器会自动为您在记录集的记录上循环。Self被重新定义为当前记录:

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

@api.multi

Self将是当前记录集,无需迭代。这是默认行为:

@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

此装饰器将旧的API调用转换为新的API签名。它允许在迁移代码时保持礼貌

@api.model 
def name(self):
    pass
需要根据方法需要定义方法装饰器,如果要从方法返回字典,则方法必须包含
@api.multi


请参阅api。当只对一条记录调用方法时,将使用一条api。它确保在使用
api.one
decorator调用方法时没有多条记录。假设您获得了记录
partner=res.partner(1,)
。它只有一条记录,并且有一个方法,例如(在
res.partner
中):

这样称呼很有效:

partner.get_name()
但是如果有更多的记录,比如
partners=res.partner(1,2,)

打电话会发出警告,告诉你只能在一张唱片上打电话。对于多个记录
api.multi
被使用,其中
self
是记录集,它可以在所有记录中迭代以执行某些操作。例如:

@api.multi
def get_partner_names(self):
    names = []
    for rec in self:
        names.append(rec.name)
    return ', '.join(names)
当您需要对模型本身执行某些操作,而不需要修改/检查某些精确模型的记录时,可以使用
api.model
。例如,可能有一个方法返回一些关于模型结构的元信息或一些帮助器方法等。文档中还说,当从旧api迁移时,这个api很好使用,因为它“礼貌地”将代码转换为新api。根据我自己的经验,如果您需要方法来返回某些东西,
model
decorator非常适合
api.one
返回空列表,因此当它应该返回某些内容时,在方法上使用
api.one
时可能会导致意外行为

更多信息:

  • 一个、多个和模型之间的差异
实际上,您可以使用包含多条记录的记录集调用
@api.one
方法。唯一的区别是,使用
@api.one
时,记录上的循环将在您定义的函数之外完成,而作为
self
,装饰程序将逐个传递记录集中的每个记录

例如,让我们在模型
示例中定义两个函数

@api.one
def print_self_one(self):
    print self

@api.multi
def print_self_multi(self):
    print self
让我们用以下方式称呼他们:

将返回:

record set: example.model(1,2)
using @api.one:
example.model(1)
example.model(2)
using @api.multi:
example.model(1,2)
因此,以下两项是等效的:

@api.one
_compute_name(self):
    self.name = "Default Name"

@api.multi
print_self_multi(self):
    for record in self:
        record.name = "Default Name"
即使使用记录集中的更多记录调用了thery

另一方面,如果不使用任何decorator,则不能使用多于(或少于)一条记录调用它,否则它会抱怨,并可能因错误而停止

@api.model
是一个完全不同的故事:如果只希望使用空记录集调用此装饰器,则只应使用此装饰器

  • 何时使用哪个
如果您希望将非空记录集作为输入值,那么在许多情况下,您可以同时使用
@api.one
@api.multi
,这只是个人喜好的问题。我个人更喜欢在可能的情况下使用
@api.one
,因为我发现这样的代码更干净(同样,对于compute和onchange方法,Odoo源代码通常使用
@api.one

在某些情况下,您只能使用
@api.multi

  • 如果您不仅希望循环记录,而且还希望只执行一次操作:

     @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"
    
  • 如果返回值很重要。用
    @api.one
    修饰的函数将始终返回一个列表(函数中作为迭代的返回值列表)。但在许多情况下,尤其是在与GUI交互时,必须返回字典(例如带有警告)。在这些情况下,您必须使用
    @api.multi


  • @api.multi

    装饰一个记录样式方法,其中
    self
    是一个记录集。方法通常定义对记录的操作。这种方法:

    @api.multi
    def method(self, args):
      ...
    
    @api.model
    def method(self, args):
    ...
    
    可以使用记录和传统样式调用,例如:

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

    装饰一个记录样式方法,其中
    self
    是一个记录集,但其内容不相关,只有模型相关。这种方法:

    @api.multi
    def method(self, args):
      ...
    
    @api.model
    def method(self, args):
    ...
    
    可以使用记录和传统样式调用,例如:

    recs = model.browse(cr, uid, ids, context)
    recs.method(args)
    
    model.method(cr, uid, ids, args, context=context)
    
    recs = model.browse(cr, uid, ids, context)
    recs.method(args)
    
    model.method(cr, uid, args, context=context)
    
    您可以在文件中找到这些装饰器的基本代码:
    odoo/api.py

    不,这是完全错误的。。。您可以在包含多条记录的记录集上调用api.one方法,它只会在记录集上循环,为每个reacord重新定义self。请参阅其他答案……此外,它不会返回空列表,而是返回每个操作的返回值列表(如果需要dict,则可能不适用于gui调用)。您对api.one的看法是正确的。我错了。在写这篇文章的时候,我以为它是这样工作的,但事实并非如此。我所描述的api.one实际上有一个方法self.sure\u one,它只允许一条记录。它通常在方法体的开头被调用。确保只对
    @api.multi
    有意义,但对
    @api.one
    没有任何作用。