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

Odoo14重写write方法更新Many2one关联模型数据报错排查

问题根因
  • 方法装饰器使用错误:write是Odoo模型的记录集级别方法,不能添加@api.model装饰器。添加该装饰器后方法签名会被修改,框架调用时传入的记录集参数会成为多余的第三个位置参数,直接触发TypeError: write() takes 2 positional arguments but 3 were given报错。
  • 关联记录更新逻辑错误:update()/write()是Odoo记录集的内置方法,不能直接在空模型集self.env["direct.statistics"]上调用,必须先定位到当前对账记录关联的那条统计数据,再对目标记录集调用更新方法。
  • 字段取值逻辑错误:create/write方法传入的values字典的键是模型字段名,不存在currency_id.id、reconciliation_act_line_ids.department_id这类带层级的键名,直接调用values.get()取这类键永远返回空值;且values中只会包含本次修改传入的字段,未修改的字段不会出现在字典中,直接从values取值会导致未修改字段被错误覆盖为空。
  • create方法逻辑缺失:创建direct.statistics记录后,没有将生成的统计记录ID赋值给当前模型的direct_statistics_id关联字段,后续更新时根本无法定位到需要同步的关联统计记录。
  • 多对多字段赋值不规范:直接给Many2many类型字段传记录集对象容易触发赋值异常,标准写法是使用Odoo的ORM命令(6, 0, 关联ID列表)完成赋值。
修正后代码
class AccountReconciliationAct(models.Model):
    _name = "account.reconciliation.act"
    direct_statistics_id = fields.Many2one(comodel_name="direct.statistics", string="Direct Statistics")

    @api.model
    def create(self, values):
        record_id = super().create(values)
        # 原有其他业务逻辑....
        if not record_id.direct_statistics_id:
            stat_record = self.env["direct.statistics"].create({
                "direct_advertiser_id": record_id.partner_id.id,
                "direct_payment_net_id": record_id.payment_net_id.id,
                "direct_currency_id": record_id.currency_id.id,
                "direct_last_act_date": record_id.reconciliation_act_date,
                "direct_total_amount": record_id.amount_total,
                "direct_department_ids": [(6, 0, record_id.reconciliation_act_line_ids.department_id.ids)]
            })
            # 绑定生成的统计记录到关联字段
            record_id.direct_statistics_id = stat_record.id
        return record_id

    # 移除write方法上错误的@api.model装饰器
    def write(self, values):
        res = super().write(values)
        # 遍历记录集兼容批量更新场景
        for record in self:
            if record.direct_statistics_id:
                # 对关联的统计记录调用write方法更新
                record.direct_statistics_id.write({
                    "direct_advertiser_id": record.partner_id.id,
                    "direct_payment_net_id": record.payment_net_id.id,
                    "direct_currency_id": record.currency_id.id,
                    "direct_last_act_date": record.reconciliation_act_date,
                    "direct_total_amount": record.amount_total,
                    "direct_department_ids": [(6, 0, record.reconciliation_act_line_ids.department_id.ids)]
                })
        return res

额外注意:direct.statistics模型中的direct_last_act_date、direct_department_ids是带计算逻辑的存储字段,如果这两个字段的compute方法本身有自动计算逻辑,手动写入的值可能被计算结果覆盖。这种场景建议直接调整对应compute方法的取值逻辑,从关联的对账记录中取数,不需要在create/write中重复写赋值逻辑,避免逻辑冲突。

内容的提问来源于stack exchange,提问作者user14213623

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 10:09:47