@ api.one,@ api.multi和@ api.model有什么区别?

时间:2015-06-29 09:54:27

标签: odoo odoo-8

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

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

4 个答案:

答案 0 :(得分:5)

仅当在一条记录上调用方法时,才使用

api.one。它确保在使用api.one装饰器调用方法时没有多个记录。假设你有记录partner = res.partner(1,)。它只有一个记录,并且有方法(例如res.partner):

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

这样称之为:

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装饰器对它有好处。 api.one返回空列表,因此当它应该返回某些内容时,在方法上使用api.one时可能会导致意外行为。

更多信息:http://odoo-new-api-guide-line.readthedocs.org/en/latest/decorator.html

答案 1 :(得分:1)

<强> api.one

这个装饰器会自动在RecordSet记录上循环。 Self被重新定义为当前记录:

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

<强> @ api.multi

Self将是没有迭代的当前RecordSet。这是默认行为:

@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

参考New API Guideline

答案 2 :(得分:1)

  • one,multi和model之间的差异

您实际上可以使用包含多个记录的RecordSet调用@api.one方法。唯一的区别是,对于@api.one,记录的循环将在您定义的函数之外完成,而self装饰器将逐个传递RecordSet中的每个记录。

例如,让我们在模型example.model中定义两个函数:

@api.one
print_self_one(self):
    print self

@api.multi
print_self_multi(self):
    print self

让我们从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()

会回来:

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。

另一方面,你不使用任何装饰器,然后它不能用一个或多于一个记录来调用,否则它会抱怨并可能因错误而停止。 / p>

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

  • 何时使用

如果您希望将非空RecordSet作为输入值,那么在许多情况下,您可以同时使用@api.one@api.multi,这只是个人偏好的问题。我个人更喜欢在可能的情况下使用@api.one,因为我发现代码更加清晰(同样,对于计算和onchange方法,Odoo源通常使用@api.one)。

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

  1. 如果您不仅想要循环记录,还希望只做一次:

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

答案 3 :(得分:0)

<强> @ api.multi

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

@api.multi
def method(self, args):
  ...
可以在记录和传统样式中调用

,例如::

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

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

<强> @ api.model

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

@api.model
def method(self, args):
...
可以在记录和传统样式中调用

,例如::

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

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

您可以在文件中找到这些装饰器的基本代码: odoo / api.py