Odoo API模块定义了Odoo环境和方法修饰符。
odoo.api.autovacuum(method)
修饰一个方法,使其由日常vacuum的cron作业(模型ir.autovacuum)调用。这通常用于垃圾收集之类的不需要特定cron作业的任务。
odoo.api.constrains(args)
约束检查的装饰器。
每个参数必须是检查记录中使用的字段名:
@api.constrains('name', 'description')
def _check_description(self):
for record in self:
if record.name == record.description:
raise ValidationError("Fields name and description must be different")
修改其中任意一个命名字段的记录就会调用。
如果验证失败,则应引发ValidationError。
**警告**
@constrains仅支持简单的字段, 以点分隔的字段名字 (关系字段的字段 e.g. partner_id.customer)不支持,将被忽略。
仅当@constrains修饰的方法中声明的字段包含在create或write调用中时才会触发。 这意味着视图中不存在的字段在创建记录期间不会触发调用. 如果要出发必须重写create以确保始终触发约束(e.g. to test the absence of value).
也可以传递一个函数作为参数。在这种情况下,通过使用模型实例调用函数来提供字段名。
odoo.api.depends(args)
返回一个decorator,该decorator指定“compute”方法的字段依赖关系。每个参数必须是一个由点分隔的字段名序列组成的字符串:
pname = fields.Char(compute='_compute_pname')
@api.depends('partner_id.name', 'partner_id.is_company')
def _compute_pname(self):
for record in self:
if record.partner_id.is_company:
record.pname = (record.partner_id.name or "").upper()
else:
record.pname = record.partner_id.name
也可以传递一个函数作为参数。在这种情况下,通过使用字段的模型调用函数来提供依赖关系。
odoo.api.depends_context(args)
返回一个修饰符,该修饰符指定非存储的“compute”方法的上下文依赖项。每个参数都是上下文字典中的一个键:
price = fields.Float(compute='_compute_product_price')
@api.depends_context('pricelist')
def _compute_product_price(self):
for product in self:
if product.env.context.get('pricelist'):
pricelist = self.env['product.pricelist'].browse(product.env.context['pricelist'])
else:
pricelist = self.env['product.pricelist'].get_default_pricelist()
product.price = pricelist._get_products_price(product).get(product.id, 0.0)
所有依赖项都必须是可哈希的。以下键具有特殊支持:
-
company(上下文或当前公司id中的值), -
uid(当前用户id和超级用户标志), -
active_test(env.context中的值或field.context中的值).
odoo.api.model(method)(github.com/odoo/odoo/b…)
修饰一个记录样式方法,其中self是一个记录集,但其内容不相关,只有模型相关。这样的方法:
@api.model
def method(self, args):
...
odoo.api.model_create_multi(method)
修饰一个方法,该方法获取字典列表并创建多个记录。可以使用单个dict或dict列表调用该方法:
record = model.create(vals)
records = model.create([vals, ...])
odoo.api.onchange(args)
返回一个decorator来修饰给定字段的onchange方法。
在出现字段的表单视图中,当修改某个给定字段时,将调用该方法。在包含表单中存在的值的伪记录上调用该方法。该记录上的字段赋值将自动发送回客户端。
每个参数必须是字段名:
@api.onchange('partner_id')
def _onchange_partner(self):
self.message = "Dear %s" % (self.partner_id.name or "")
return {
'warning': {'title': "Warning", 'message': "What is this?", 'type': 'notification'},
}
如果类型设置为通知,则警告将显示在通知中。否则,它将作为默认值显示在对话框中。
**警告**
@onchange仅支持简单字段名,不支持点名称(关系字段的字段 e.g. `partner_id.tz`) 将被忽略
**危险**
由于@onchange返回伪记录的记录集,因此对上述记录集调用任何一个CRUD方法(create()、read()、write()、unlink())都是未定义的行为,因为它们可能还不存在于数据库中。
相反,只需像上面的示例中所示那样设置记录的字段,或者调用update()方法。
**警告**
one2many或many2many字段不可能通过onchange修改自身。这是一个Web客户端限制 - see 
odoo.api.ondelete(*, at_uninstall)
标记要在unlink()期间执行的方法。
此装饰器的目标是,如果从业务角度来看,删除记录没有意义,则在取消链接记录时允许客户端错误。例如,用户不能删除已验证的销售订单。
虽然这可以通过简单地重写模型上的方法unlink来实现,但它的缺点是与模块卸载不兼容。卸载模块时,重写可能会引发用户错误,但我们不必担心,因为模块正在卸载,因此无论如何都应该删除与模块相关的所有记录。
这意味着通过重写unlink,很可能会有一些表/记录保留为卸载模块中的剩余数据。这会使数据库处于不一致的状态。此外,如果在该数据库上重新安装模块,则存在冲突的风险。
用@ondelete修饰的方法应在某些条件下引发错误,按照惯例,该方法应命名为_unlink_if_<condition> 或 _unlink_except_<not_condition>.
@api.ondelete(at_uninstall=False)
def _unlink_if_user_inactive(self):
if any(user.active for user in self):
raise UserError("Can't delete an active user!")
# same as above but with _unlink_except_* as method name
@api.ondelete(at_uninstall=False)
def _unlink_except_active_user(self):
if any(user.active for user in self):
raise UserError("Can't delete an active user!")
- Parameters at_uninstall (bool) – 如果正在卸载实现所述方法的模块,是否应调用修饰方法。几乎应始终为
False,以便模块卸载不会触发这些错误。
**危险**
只有当卸载模块时,您正在执行的检查也适用时,参数at_uninstall才应设置为True。
例如,在卸载sale时,是否删除已验证的销售订单并不重要,因为无论如何都应删除与sale相关的所有数据,在这种情况下,at_uninstall应设置为False。
但是,如果没有安装其他语言,则阻止删除默认语言是有意义的,因为删除默认语言会破坏许多基本行为。在这种情况下,at_uninstall应设置为True。
odoo.api.returns(model, downgrade=None, upgrade=None)
为返回model实例的方法返回修饰符。
-
Parameters
-
model – 模型名称,或当前模型的
self -
downgrade – 一个函数
downgrade(self,value,*args,**kwargs),用于将记录样式value转换为传统样式输出 -
upgrade – 函数
upgrade(self,value,*args,**kwargs)将传统样式value转换为记录样式输出
-
参数self、*args和**kwargs是以记录样式传递给方法的参数。
装饰器将方法输出调整为api样式:传统样式为id、ids或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)
请注意,修饰方法必须满足该约定。
这些修饰器是自动inherited:重写修饰的现有方法的方法将用相同的@return(model)修饰。
欢迎关注公众号