Method decorators(装饰器)
该模块提供的元素用于管理两种不同API样式,即“traditional”(“传统”)和 “record”(“记录”)风格。
在“traditional” 风格中,诸如数据库游标、用户id、context字典和记录集ids(通常表示为cr,uid,context,id)参数都是显式的传递给各方法。在“record”样式中,这些参数被封装在模型实例中,这使其具有更加面向对象的感觉。
例如,声明:
model = self.pool.get(MODEL)
ids = model.search(cr, uid, DOMAIN, context=context)
for rec in model.browse(cr, uid, ids, context=context):
print rec.name
model.write(cr, uid, ids, VALUES, context=context)
也可以写成:
env = Environment(cr, uid, context) # cr, uid, context wrapped in env
model = env[MODEL] # retrieve an instance of MODEL
recs = model.search(DOMAIN) # search returns a recordset
for rec in recs: # iterate over the records
print rec.name
recs.write(VALUES) # update all records in recs
用传统方式写的方法会启发性的自动根据一些基于参数名称进行装饰。
odoo.api.multi(method)
装饰一个"record-style"方法,其中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)
odoo.api.model(method)
装饰一个"record-style"方法,但它的内容不相关,只有模型。例如:
@api.model
def method(self, args):
...
在记录样式和传统样式中调用,例如:
# recs = model.browse(cr, uid, ids, context)
recs.method(args)
model.method(cr, uid, args, context=context)
请注意,没有 ids 以传统方式传递给方法。
odoo.api.depends(*args)
返回一个装饰器,它指定字段所依赖的“compute”方法(对于新样式中功能字段)。
每个参数必须是一个字符串,该字符串由以点分隔的字段名称序列组成:
pname = fields.Char(compute='_compute_pname')
@api.one
@api.depends('partner_id.name', 'partner_id.is_company')
def _compute_pname(self):
if self.partner_id.is_company:
self.pname = (self.partner_id.name or "").upper()
else:
self.pname = self.partner_id.name
也可以将单个函数作为参数传递。在这种情况下,通过使用字段的模型调用函数来给出依赖关系。
odoo.api.constrains(*args)
装饰约束检查器。每个参数必须是检查中使用的字段名称:
@api.one
@api.constrains('name', 'description')
def _check_description(self):
if self.name == self.description:
raise ValidationError("Fields name and description must be different")
当命名字段做出修改之后调用。
如果验证失败,则会触发***ValidationError***。
Warning
@constrains 只支持简单的字段名称,通过点出来的字段(关系字段的字段,例如partner_id.customer)不被支持且被忽略。
@constrains 只有当在create或write调用中包含装饰方法中的声明字段时才会触发。这意味着视图中不存在的字段在创建记录期间不会触发调用。重写create时必须确保始终触发约束(例如,测试缺少值)。
odoo.api.onchange(*args)
返回装饰器以装饰给定字段的onchange方法。每个参数必须是字段名称:
@api.onchange('partner_id')
def _onchange_partner(self):
self.message = "Dear %s" % (self.partner_id.name or "")
在字段显示的form视图中,当修改其中一个给定字段时,将调用该方法。在包含form中存在的值的 伪记录 上调用该方法。该记录上的字段更改值会自动发送回客户端。
该方法也可以返回字典以更改domains并弹出警告消息,就像在旧API中一样:
return {
'domain': {'other_id': [('partner_id', '=', partner_id)]},
'warning': {'title': "Warning", 'message': "What is this?"},
}
Warning
只支持简单字段,通过点出来的字段(关系字段的字段,例如partner_id.tz)不被支持且被忽略。
odoo.api.returns(model, downgrade=None, upgrade=None)
返回返回模型实例的方法的装饰器。
Parameters:
model – 模型名称,或者当前模型对应的 self
downgrade – 方法 downgrade(self, value, *args, **kwargs) 将记录样式值转换为传统样式的输出
upgrade – 方法 upgrade(self, value, *args, **kwargs) 将传统风格的值转换为记录式输出
参数self,* args和 **kwargs是以记录样式传递给方法的参数。
对于传统风格和记录样式的记录集,装饰器将方法输出调整为api样式: id, ids or False 。
@model
@returns('res.partner')
def find_partner(self, arg):
... # return some record
# output depends on call style: traditional vs record style
partner_id = model.find_partner(cr, uid, arg, context=context)
# recs = model.browse(cr, uid, ids, context)
partner_record = recs.find_partner(arg)
请注意,修饰方法必须满足约定。
装饰器会自动继承:重写装饰的现有方法的方法必须使用相同的方法 @returns(model) 进行修饰。
odoo.api.one(method)
装饰一个记录样式的方法,其中self应该是一个单例实例。装饰方法自动循环记录并列出结果列表。如果方法用returns()修饰,它会连接生成的实例。例如:
@api.one
def method(self, args):
return self.name
可以在记录和传统样式中调用,例如:
# recs = model.browse(cr, uid, ids, context)
names = recs.method(args)
names = model.method(cr, uid, ids, args, context=context)
从版本9.0开始不推荐使用:one() 经常使代码不那么清晰,并且时不时以开发人员和读者想不到的地方出现问题。
强烈建议使用 multi() ,要么迭代自记录集,要么确保记录集是带有ensure_one()的单个记录。
odoo.api.v7(method_v7)
装饰一个只支持旧式api的方法,可以通过重新定义具有相同名称并用v8()修饰的方法来提供新式api:
@api.v7
def foo(self, cr, uid, ids, context=None):
...
@api.v8
def foo(self):
...
如果一种方法调用另一种方法,则必须特别小心.因为该方法可能被重写。应该从当前的类中调用该方法(say MyClass),例如:
@api.v7
def foo(self, cr, uid, ids, context=None):
# Beware: records.foo() may call an overriding of foo()
records = self.browse(cr, uid, ids, context)
return MyClass.foo(records)
请注意,装饰器方法使用第一种方法的文档字符串。
odoo.api.v8(method_v8)
Decorate a method that supports the new-style api only。可以通过重新定义具有相同名称的方法并使用v7()修饰来提供旧式api:
@api.v8
def foo(self):
...
@api.v7
def foo(self, cr, uid, ids, context=None):
...
请注意,装饰器方法使用第一种方法的文档字符串。