Odoo中如何正确复制One2many字段以避免报错及原数据丢失?
Odoo One2many字段复制问题解决方案
之前尝试的错误原因
- 直接给字段加
copy=True报错:project.assignment模型内的约束、计算字段没有处理多记录集,触发了单例校验报错;且One2many字段默认copy=False,强制开启需要配套关联模型的复制逻辑适配。 - 第一次重写copy方法报错:存在两个逻辑漏洞
- 循环内用
self.assignment_ids而非rec.assignment_ids,@api.multi装饰器下self是多记录集,直接取关联字段会拿到所有项目的assignment,不符合单条记录复制的逻辑 - 新建关联记录的
(0,0, values)语法中不需要传id参数,0命令本身代表新建记录,强制传入已有id会触发ORM的关联校验错误
- 循环内用
- 第二次重写copy方法丢失原数据:
6命令的作用是「用指定id的记录替换当前关联字段」,本质是修改这些project.assignment的外键project_id到新项目,原项目自然就失去了这些关联记录,完全不符合复制需求
正确的实现代码
@api.multi def copy(self, default=None): default = default or {} # copy方法本身为单例操作,multi模式下逐条处理每条记录 result_records = self.browse() for rec in self: new_assignments = [] # 仅取当前要复制的项目的关联assignment for assignment in rec.assignment_ids: new_assignments.append((0, 0, { 'role_id': assignment.role_id.id, 'date_join': date.today(), 'user_id': assignment.user_id.id, # 不需要传id、project_id,ORM会自动关联到新复制的项目 })) # 单独生成当前记录的default,避免多记录复制时参数覆盖 rec_default = default.copy() rec_default['assignment_ids'] = new_assignments # 调用父类复制方法,把结果追加到返回集 result_records += super(ProjectProject, rec).copy(rec_default) return result_records
可选优化方案
如果后续复制时不需要自定义字段值(比如date_join不需要改成当前日期,直接复用原值),也可以直接给assignment_ids加copy=True,同时去project.assignment模型排查所有触发单例报错的代码,给缺少self.ensure_one()的方法补全校验,修正多记录处理逻辑即可。
内容的提问来源于stack exchange,提问作者Tung Van
相关产品推荐
相关产品推荐

