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
相关产品推荐
相关产品推荐

