You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Odoo中如何正确复制One2many字段以避免报错及原数据丢失?

Odoo One2many字段复制问题解决方案

之前尝试的错误原因

  • 直接给字段加copy=True报错:project.assignment模型内的约束、计算字段没有处理多记录集,触发了单例校验报错;且One2many字段默认copy=False,强制开启需要配套关联模型的复制逻辑适配。
  • 第一次重写copy方法报错:存在两个逻辑漏洞
    1. 循环内用self.assignment_ids而非rec.assignment_ids,@api.multi装饰器下self是多记录集,直接取关联字段会拿到所有项目的assignment,不符合单条记录复制的逻辑
    2. 新建关联记录的(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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 09:57:03