ODOO 13社区版One2many关联项保存事件需求
Hey Lars, great question! This is totally a common use case, and while Odoo doesn't ship with a direct @api.onsave decorator, there are straightforward ways to achieve exactly what you need—triggering logic when a new One2many line item is saved, and accessing the newly created line.
最直接的方法:重写子模型的create方法
When you save a new One2many line from the parent form, Odoo actually calls the create method of the One2many's associated model. Overriding this method lets you hook into the exact moment the line is saved, and you'll get the fully created line object right away.
Here's a code example:
from odoo import models, api, fields class YourOne2manyLine(models.Model): _name = 'your.one2many.line' _description = 'One2many Line Item' # 假设你的外键字段关联到父模型 parent_id = fields.Many2one('your.parent.model', string='Parent') name = fields.Char(string='Line Name') # 其他业务字段... @api.model def create(self, vals): # 先调用父类create方法完成新行的数据库存储 new_line = super(YourOne2manyLine, self).create(vals) # 在这里编写你的业务逻辑,new_line就是刚保存的新行项目 # 比如打印字段值、触发关联动作,或者直接返回它(默认已返回) print(f"新行已保存:ID={new_line.id},名称={new_line.name}") return new_line
这个方法的优势在于,每新增并保存一条One2many行时,create方法会在数据持久化后立即执行,你可以直接拿到完整的新行记录,完全匹配你需要的场景。
备选方案:从父模型监听One2many更新
如果你需要从父模型层面处理新行保存的逻辑,可以重写父模型的write方法,以此检测One2many字段的新增操作:
from odoo import models class YourParentModel(models.Model): _name = 'your.parent.model' _description = 'Parent Model' one2many_lines = fields.One2many('your.one2many.line', 'parent_id', string='Line Items') def write(self, vals): # 检查是否有One2many字段的更新操作 if 'one2many_lines' in vals: # One2many的更新值采用特殊元组格式:(操作类型, 记录ID, 字段值) for op in vals['one2many_lines']: if op[0] == 0: # 操作类型0代表"创建新记录",op[2]是新行的字段值 # 注意:此时新行还未完成数据库存储,若需要拿到最终记录,子模型的create方法仍是更优选择 print(f"准备创建新行,字段值:{op[2]}") # 调用父类write方法完成父模型的保存 return super(YourParentModel, self).write(vals)
为什么@api.onchange不符合需求
正如你所说,@api.onchange是在用户编辑行项目时触发(尚未保存到数据库),无法获取到持久化后的最终记录。而重写子模型create方法的方式,正好在数据保存完成后执行,完美满足你需要获取新行项目的要求。
你并没有遗漏什么——Odoo确实没有专门的@api.onsave装饰器,但上面的方法是社区版中处理这类场景的标准方案。
内容的提问来源于stack exchange,提问作者Lars

