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

Odoo17中One2many字段删除记录保存后重现问题求助

Odoo 17多One2many字段删除记录后恢复的解决办法

问题根源

你遇到的问题核心是:同一个elections.member模型被三个One2many字段关联,Odoo默认对One2many的删除操作是解除关联(仅把member的election_id设为空),但多个One2many字段的存在会导致Odoo在刷新记录集时,误将未彻底移除的记录重新加载回列表;另外字段定义和视图的domain不一致,也可能让符合条件的记录再次显示。

解决方案

方案1:修改One2many字段的删除行为(物理删除)

如果业务允许直接删除elections.member记录,在One2many字段定义中添加ondelete='cascade',这样删除列表中的记录时会直接物理删除该member,彻底避免恢复:

member_ids = fields.One2many('elections.member', 'election_id', string='Members',                                
domain=[('is_observer','=', False )], ondelete='cascade')        
 
observer_ids=fields.One2many('elections.member', 'election_id',string='Observers',                             
domain=[('is_observer','=', True ), ('is_candidate','=', False )], ondelete='cascade')  

all_member_ids=fields.One2many('elections.member', 'election_id',string='All members (including observers and candidates)', ondelete='cascade')

方案2:改用计算字段分组(推荐,避免多One2many冲突)

保留一个实际存储关联的One2many字段,另外两个分组用计算字段实现,从根源上避免多One2many的记录集混淆:

模型代码修改:

# 仅保留一个实际存储关联的字段
all_member_ids = fields.One2many('elections.member', 'election_id', string='All members')

# 计算字段实现成员分组
member_ids = fields.One2many('elections.member', compute='_compute_member_ids', inverse='_inverse_member_ids', string='Members')
observer_ids = fields.One2many('elections.member', compute='_compute_observer_ids', inverse='_inverse_observer_ids', string='Observers')

def _compute_member_ids(self):
    for rec in self:
        # 过滤出非观察者、非候选人的成员
        rec.member_ids = rec.all_member_ids.filtered(lambda m: not m.is_observer and not m.is_candidate)

def _inverse_member_ids(self):
    for rec in self:
        # 处理新增记录:自动设置属性并关联当前选举
        for member in rec.member_ids:
            member.is_observer = False
            member.is_candidate = False
            member.election_id = rec.id
        # 处理删除记录:解除关联
        removed_members = rec.all_member_ids - rec.member_ids
        for member in removed_members.filtered(lambda m: not m.is_observer and not m.is_candidate):
            member.election_id = False

def _compute_observer_ids(self):
    for rec in self:
        # 过滤出观察者、非候选人的成员
        rec.observer_ids = rec.all_member_ids.filtered(lambda m: m.is_observer and not m.is_candidate)

def _inverse_observer_ids(self):
    for rec in self:
        # 处理新增记录:自动设置属性并关联当前选举
        for member in rec.observer_ids:
            member.is_observer = True
            member.is_candidate = False
            member.election_id = rec.id
        # 处理删除记录:解除关联
        removed_members = rec.all_member_ids - rec.observer_ids
        for member in removed_members.filtered(lambda m: m.is_observer and not m.is_candidate):
            member.election_id = False

视图代码无需修改

原来的视图中member_ids和observer_ids的配置可以直接保留,计算字段会自动处理数据的显示和编辑逻辑。

方案3:统一字段与视图的Domain

确保字段定义的domain和视图中的domain完全一致,避免Odoo刷新时加载不符合视图过滤条件但符合字段定义的记录:
比如member_ids字段定义的domain加上('is_candidate','=', False ),和视图保持一致:

member_ids = fields.One2many('elections.member', 'election_id', string='Members',                                
domain=[('is_observer','=', False ), ('is_candidate','=', False )])        

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 23:44:57