点击保存按钮时,Odoo的create和write方法如何触发?
嘿,我来给你拆解一下Odoo里点击保存按钮时create和write方法的执行逻辑,结合你贴的模型代码来讲会更清楚~
Odoo保存按钮触发的
create/write方法执行流程 Odoo的保存按钮其实对应两种场景:新建记录和编辑已有记录,分别触发create和write方法,逻辑略有不同,下面分开说:
1. 新建记录时的create方法执行流程
当你在空白表单里填完所有必填字段(比如你模型里的name、code、key_letter这些),点击保存的那一刻:
- 前端会把你填写的所有字段数据打包成JSON,发送给Odoo后端的Web控制器;
- 后端会定位到你对应的
health_administrator.medical_procedure_base模型,调用它的create方法; - 默认的
create方法(继承自models.Model)会按顺序做这些事:- 先验证字段约束:比如检查所有
required=True的字段有没有填,没填直接抛错误,前端会弹出提示阻止创建; - 处理关联字段:比如你的
key_letter是Many2one,Odoo会自动验证你选的关联记录是否存在,确保外键关联合法; - 把处理好的数据写入数据库对应的表(Odoo会自动生成表名
health_administrator_medical_procedure_base); - 触发一系列ORM钩子:比如字段的
compute方法(如果有的话)、模型上的@api.model_create_multi装饰器逻辑等; - 最后把新建记录的ID返回给前端,页面跳转到这条记录的详情页。
- 先验证字段约束:比如检查所有
2. 编辑已有记录时的write方法执行流程
当你打开一条已有的记录,修改部分字段后点击保存:
- 前端只会把你修改过的字段加上这条记录的ID打包发送给后端(不会传所有字段,节省资源);
- 后端调用模型的
write方法; - 默认的
write方法会做这些事:- 先检查权限:确保当前用户有修改这条记录的权限;
- 验证字段约束:比如如果把
name清空了,会触发必填校验报错; - 处理关联字段更新:比如你换了
medical_procedure_cat_id,Odoo会更新对应的外键值,同时处理反向关联的逻辑; - 只更新数据库中变化的字段(不是全量更新);
- 触发ORM钩子:比如字段的
compute方法、模型上的@api.multi装饰器逻辑等; - 返回成功状态给前端,页面刷新显示修改后的内容。
结合你的模型代码的具体例子
你的模型定义了几个核心必填字段,举个实际场景:
class medical_procedure_base(models.Model): _name = 'health_administrator.medical_procedure_base' _description = 'Medical Procedure' name = fields.Char(string='标签', required=True) code = fields.Char(string='编码', required=True) key_letter = fields.Many2one('health_administrator.key_letter', required=True, string="关键字母") medical_procedure_cat_id = fields.Many2one('health_administrator.medical_procedure_category', required=True, string="操作类别") # 你代码里的amoun...应该是金额字段,假设是amount = fields.Float(string='金额')
- 新建时:如果
key_letter没选,点击保存会直接弹出“关键字母是必填项”的提示,create方法不会执行数据库写入; - 编辑时:如果你只修改了
name,write方法只会更新数据库里这条记录的name字段,其他字段保持不变。
自定义create/write方法的小提示
如果你想在保存时加自己的逻辑(比如自动生成编码、记录修改日志),可以重写这两个方法,但一定要记得调用父类的方法,不然默认的校验、字段处理逻辑会丢失:
from odoo import models, fields, api class medical_procedure_base(models.Model): # 你的模型定义... @api.model def create(self, vals): # 自定义逻辑:自动生成编码 vals['code'] = self.env['ir.sequence'].next_by_code('medical.procedure.code') or 'DEFAULT_CODE' # 必须调用父类的create方法,否则默认逻辑失效 return super(medical_procedure_base, self).create(vals) def write(self, vals): # 自定义逻辑:修改编码时记录日志 if 'code' in vals: self.env['medical.procedure.log'].create({ 'procedure_id': self.id, 'old_code': self.code, 'new_code': vals['code'], 'change_date': fields.Date.today() }) # 必须调用父类的write方法 return super(medical_procedure_base, self).write(vals)
内容的提问来源于stack exchange,提问作者Marcel Brou
相关产品推荐
相关产品推荐

