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

Odoo中write方法递归调用引发栈溢出问题的解决咨询

解决Odoo模型Write方法互相递归的上下文方案

这个递归死循环问题在Odoo中模型互相触发写操作时非常典型,通过上下文标记来阻断递归链是最简洁且不污染数据库的解决方案——核心思路就是在触发对方模型的write时,通过上下文告诉对方“这次操作是我发起的,你别再回调我了”。

具体修改步骤

我会基于你的代码给出完整的修改版,关键是在跨模型调用write时添加上下文标记,同时在自身的write方法里检查这个标记,避免触发回调:

1. 修改SomeOrder模型的代码

class SomeOrder(models.Model):
    _inherit = 'some.order'

    @api.multi
    def write(self, vals):
        result = super(SomeOrder, self).write(vals)
        # 检查上下文:如果是从OtherOrder触发的write,就跳过后续回调
        if not self.env.context.get('from_other_order'):
            for rec in self:
                rec.update_other_order()
        return result

    def update_other_order(self):
        # 这里是你的业务逻辑,假设你要更新对应的OtherOrder记录
        for rec in self:
            other_order = self.env['other.order'].search([('some_order_id', '=', rec.id)])
            # 调用OtherOrder的write时,添加上下文标记,说明是从SomeOrder过来的
            other_order.with_context(from_some_order=True).write({
                # 你的更新字段,比如:
                # 'some_field': rec.some_value
            })

2. 修改OtherOrder模型的代码

class OtherOrder(models.Model):
    _inherit = "other.order"

    @api.multi
    def write(self, vals):
        result = super(OtherOrder, self).write(vals)
        # 检查两个条件:一是更新了amount_paid,二是不是从SomeOrder触发的write
        if 'amount_paid' in vals and not self.env.context.get('from_some_order'):
            self.update_some_order()
        return result

    def update_some_order(self):
        # 这里是你的业务逻辑,假设你要更新对应的SomeOrder记录
        for rec in self:
            some_order = self.env['some.order'].search([('id', '=', rec.some_order_id.id)])
            # 调用SomeOrder的write时,添加上下文标记,说明是从OtherOrder过来的
            some_order.with_context(from_other_order=True).write({
                # 你的更新字段,比如:
                # 'another_field': rec.another_value
            })

为什么这个方案有效?

Odoo的context是当前调用链中的临时状态容器,不会持久化到数据库,只会在本次请求/方法调用中传递:

  • 当SomeOrder主动调用OtherOrder.write时,通过with_context(from_some_order=True)标记来源
  • OtherOrder的write方法检测到这个标记后,就不会触发update_some_order,从而阻断递归
  • 反过来,OtherOrder主动调用SomeOrder.write时也标记来源,SomeOrder的write方法会跳过回调

注意事项

  • 上下文的键名(比如from_some_order、from_other_order)尽量取唯一的名字,避免和Odoo内置或其他自定义上下文冲突
  • 确保所有跨模型触发write的地方都添加上下文标记,包括你业务逻辑中可能存在的其他触发点
  • 如果你的update_xxx_order方法里有批量操作,也要确保批量write时带上上下文

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:17:28