Odoo 9更新影响计算字段的值时触发AssertionError报错求助
我来帮你梳理下这个Odoo 9里遇到的断言错误问题,结合我处理这类问题的经验,给你几个常见的排查方向和解决办法:
问题回顾
当你尝试更新会影响计算字段的值时,触发了如下服务器错误:
AssertionError: assert self in records and field in fs
完整的错误回溯(片段):
Traceback (most recent call last): File "/Users/abdalla/projects/greenway/odoo-server/openerp/http.py", line 647, in _handle_exception return super(JsonRequest, self)._handle_exception(exception) File "/Users/abdalla/projects/greenway/odoo-server/openerp/http.py", line 684, in dispatch result = self._call_function(**self.params) File "/Users/abdalla/projects/greenway/odoo-server/openerp/http.py", line ...
常见原因与修复方案
1. 计算字段的依赖定义出错
这是最常见的原因——计算字段的@api.depends()装饰器里要么漏写了依赖字段,要么字段名称拼写错误。Odoo追踪计算字段的更新全靠这些依赖,一旦出错,就会在更新时触发断言失败。
修复步骤:
检查你定义计算字段的代码,确保depends里列出的所有字段都和模型中实际定义的字段名完全一致,包括关联字段的层级。比如:
# 正确示例:明确列出所有依赖字段 @api.depends('partner_id.credit_limit', 'amount_due') def _compute_credit_available(self): for rec in self: rec.credit_available = rec.partner_id.credit_limit - rec.amount_due
2. 批量操作时记录集处理不当
如果你在自定义方法里手动处理记录集(比如过滤、切片),但后续更新字段时用了错误的记录集,就会出现self不在当前操作记录集中的情况。比如你过滤出一部分记录后,却还是用原始的self去写字段。
修复步骤:
操作记录集时,始终基于过滤后的新记录集进行字段更新。推荐用Odoo内置的filtered()或search()方法返回有效记录集:
def mark_as_completed(self): # 正确做法:过滤出符合条件的记录,再执行更新 draft_records = self.filtered(lambda r: r.state == 'draft') draft_records.write({'state': 'completed'})
3. 存储型计算字段的依赖冲突
如果你的计算字段设置了store=True(即存储到数据库),但依赖的字段是未存储的关联字段(比如related字段没设store=True),Odoo无法追踪到依赖字段的变化,进而触发断言错误。
修复步骤:
对于store=True的计算字段,确保所有依赖字段要么是存储型字段,要么关联字段也设置了store=True。比如:
# 关联字段设置store=True,才能作为存储型计算字段的依赖 partner_credit = fields.Float(related='partner_id.credit_limit', store=True) @api.depends('partner_credit', 'amount_due') def _compute_remaining_credit(self): for rec in self: rec.remaining_credit = rec.partner_credit - rec.amount_due
4. 绕过ORM直接操作数据库
如果你直接用SQL语句更新数据库,而没有通过Odoo的write()/create()等ORM方法,ORM层无法感知字段变化,缓存和实际数据不一致,就会触发断言错误。
修复步骤:
尽量使用Odoo提供的ORM方法修改数据;如果必须用SQL,执行后一定要调用invalidate_cache()刷新缓存:
def update_via_sql(self): self.env.cr.execute("UPDATE my_model SET is_active = True WHERE id IN %s", (tuple(self.ids),)) # 刷新相关字段的缓存 self.invalidate_cache(['is_active'])
内容的提问来源于stack exchange,提问作者abdalla elsayed

