Odoo 10筛选后删除关联记录异常:全部关联记录被误删
解决Odoo自定义表单中One2Many筛选后删除导致全部记录丢失的问题
这个问题我之前踩过坑!核心原因是Odoo处理One2Many字段的机制:当你提交表单时,前端只会把当前可见的One2Many记录数据传给后端。那些被筛选隐藏的记录,因为没出现在提交的表单数据里,后端会默认把它们标记为「需要删除」,哪怕你根本没碰过它们。
为什么会这样?
Odoo的One2Many字段是通过一组操作指令来同步数据的,比如:
(2, id):删除指定ID的记录(4, id):关联已存在的记录- 如果你提交的指令里没有包含某个已关联的One2Many记录ID,后端就会认为你要解除它的关联(甚至删除,取决于字段的
ondelete设置)。当你筛选后只操作可见记录时,隐藏的记录自然不会出现在提交指令里,结果就被误删了。
几个可行的解决方案
1. 临时应急方案:取消筛选后再操作
如果只是临时处理,最简单的办法就是删除前先取消One2Many列表的筛选,让所有记录都显示出来,再找到要删除的那条操作。这样提交时所有记录都会被包含,不会被误删。但这只是治标不治本,用户体验也不好。
2. 前端层面:修改组件逻辑,确保提交时包含所有有效记录
你可以自定义One2Many字段的前端组件,在表单提交前自动取消筛选,让所有未被删除的记录都回到视图中,再触发提交。比如重写FieldOne2Many的保存相关方法:
odoo.define('your_module.one2many_fix', function(require) { "use strict"; var FieldOne2Many = require('web.relational_fields').FieldOne2Many; FieldOne2Many.include({ _onSave: function () { // 先取消当前列表的筛选 if (this.listController) { this.listController.searchView.clear(); } // 再执行原有的保存逻辑 this._super.apply(this, arguments); } }); });
这个方法能保证提交时所有记录都被包含,但需要你有前端开发的基础。
3. 后端层面:重写父模型的write方法,过滤误删逻辑
最稳妥的办法是在后端控制数据同步逻辑,只删除那些明确标记要删除的记录,忽略那些因为筛选没被提交的记录。比如重写Model A的write方法:
from odoo import models, api class ModelA(models.Model): _inherit = 'model.a' # 替换成你的父模型技术名称 @api.multi def write(self, vals): # 只处理One2Many字段b_ids的情况 if 'b_ids' in vals: # 拆分操作指令:提取明确要删除的记录ID,保留其他操作 delete_ids = [] valid_operations = [] for op in vals['b_ids']: # Odoo的One2Many操作格式:(操作码, ID, 数据) if op[0] == 2: # 2是删除操作 delete_ids.append(op[1]) else: valid_operations.append(op) # 获取当前模型中所有未被明确删除的B记录ID remaining_b_ids = self.b_ids.filtered(lambda b: b.id not in delete_ids).ids # 把这些剩余的记录添加到操作指令里,确保后端不会误删 for b_id in remaining_b_ids: # 检查是否已经在操作指令中,避免重复添加 exists = any(op[0] == 4 and op[1] == b_id for op in valid_operations) if not exists: valid_operations.append((4, b_id)) # 替换原有的b_ids操作指令 vals['b_ids'] = valid_operations # 执行父类的write方法 return super(ModelA, self).write(vals)
这个方法从根源上避免了误删,不管前端有没有筛选,后端只会处理你明确要删除的记录,其他记录都会被保留。
注意事项
- 如果你用的是Odoo 14+,
@api.multi可以换成@api.model,根据版本调整语法。 - 测试时要注意One2Many字段的
ondelete设置,如果是cascade,可能需要额外处理,但上面的代码已经覆盖了大部分场景。
内容的提问来源于stack exchange,提问作者Cuu Nguyen
相关产品推荐
相关产品推荐

