即使一个人,也要活得像军队一样!

Odoo13-- api装饰器详解

最近有些小伙伴对Odoo的api中的装饰器总是有些误区,或者使用方式不对。导致结果和预想的不一致。

那么可以肯定的说,那是你使用姿势的问题。下面且听我讲解姿势,如:老汉推车…… 咳咳,跑偏了。

api装饰器种类

姿势一: @api.model

装饰一个记录样式的方法,其中self是一个记录集,但其内容无关紧要,仅模型相关。
即在记录行方式下装饰一个内容不明确、但模型明确的方法。
举个姿势:

1
2
3
@api.model
def method(self, args):
...

特别提示,此姿势应用在create方法中,会给create方法使用默认的装饰器model_create_single

姿势二: @api.onchange(*args)

装饰给定字段的onchange方法。就是当字段发生改变时,触发绑定的函数。
举个姿势:

1
2
3
@api.onchange('partner_id')
def _onchange_partner(self):
self.message = "Dear %s" % (self.partner_id.name or "")

在该字段出现的表单视图中,修改给定字段之一时将调用该方法。
该姿势还可应用于动态domain、警告提示

1
2
3
4
5
6
@api.onchange('partner_id')
def _onchange_partner(self):
return {
'domain': {'other_id': [('partner_id', '=', partner_id)]},
'warning': {'title': "Warning", 'message': "What is this?", 'type': 'notification'},
}

注意:
1.如果类型设置为通知,则警告将显示在通知中。否则,它将默认显示在对话框中。
2.由于@ onchange返回伪记录的记录集, 因此调用任何一种CRUD方法的行为是不确定的,因为它们可能尚不存在于数据库中。相反,只需如示例中所示设置记录的字段,或调用:meth:update方法。
3.@ onchange仅支持简单的字段名称,点分名称 (关系字段的字段,例如``partner_id.tz’’)不支持,将被忽略
4.表单视图中一定要存在字段,否则不调用

姿势三: @api.constrains(*args)

约束检查装饰器。每个参数必须是一个字段名称。
在已修改命名字段之一的记录上调用。
举个姿势:

1
2
3
4
5
@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")

注意:
1、@ constrains仅支持简单的字段名称,点分名称(关系字段的字段,例如partner_id.customer)不支持,将被忽略
2、仅在create或write调用中才触发@ constrains。这意味着视图中不存在的字段不会触发调用

姿势四: @api.depends(*args)

返回一个装饰器,该装饰器指定compute方法的字段相关性(对于新型函数字段)。
每个参数必须是字段或者一个由点号分隔的字段名称序列组成的字符串。
举个姿势:

1
2
3
4
5
6
7
8
9
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

姿势五: @api.depends_context(*args)

返回一个装饰器,该装饰器指定非存储的compute方法。每个参数都是上下文的键
举个姿势:

1
2
3
4
5
6
7
8
9
10
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)

注意:
所有依赖项必须是可哈希的。以下按键有特殊
支持:
-force_company(上下文值或当前公司ID),
-uid(当前用户ID和超级用户标志),
-active_test(env.context中的值或field.context中的值)。

姿势六: @api.returns(model, downgrade=None, upgrade=None)

用于返回model实例的一个装饰器
举个姿势:

1
2
3
4
5
6
7
8
9
10
11
12
@model
@returns('res.partner')
def find_partner(self, arg):
... # return some record

# output depends on call style: traditional vs record style

# 1.traditional
partner_id = model.find_partner(cr, uid, arg, context=context)
# 2.record style
recs = model.browse(cr, uid, ids, context)
partner_record = recs.find_partner(arg)

姿势七: @api.model_create_multi(method)

装饰一个采用字典列表并创建多个记录的方法。 可以使用单个字典或列表的形式调用该方法。
举个姿势:

1
2
3
4
5
6
7
@api.model_create_multi
def create(self, vals_list):
self._check_create()
return super(ProductionLot, self).create(vals_list)

record = model.create(vals)
records = model.create([vals, ...])

姿势八: @api.model_create_single(method)

装饰一个采用字典并创建单个记录的方法。 默认是这个。

姿势九: @api.multi 和 @api.one 在Odoo13 已经阉割


以上为Odoo13开发中常用的所有的api装饰器了。
祝大家早点掌握姿势,实践出真理。实在不行就换个姿势,再来一次。

-------------本文结束感谢您的阅读-------------