Odoo创建记录前校验One2many字段重复值问题排查
问题根因
现有约束方法无法生效的核心问题有三点:
- 取值逻辑错误:
self.mdm_versions_ids.version是多记录的字段值集合,不是单个版本字符串,无法直接用于重复判断 - 判断逻辑错误:将版本字符串和One2many记录集对象直接做成员比对,逻辑完全不成立,永远不会触发报错
- 触发范围不全:仅监听
mdm_versions_ids.version,新增/删除One2many行时不会触发校验,存在漏判场景
修复方案
不需要修改create/write方法,直接调整约束方法逻辑即可,修复后完整代码如下:
from odoo import models, fields, api from odoo.exceptions import ValidationError class MDMSolutions(models.Model): _name = 'mdm.solutions' _inherit = ['mail.thread', 'mail.activity.mixin'] _description = "MDM Versions" _rec_name = 'name' name = fields.Char('Name', tracking=True, required=True) mdm_versions_ids = fields.One2many( 'mdm.solutions.versions', 'mdm_class_id', string="MDM Versions") @api.constrains('mdm_versions_ids', 'mdm_versions_ids.version') def check_for_doubles(self): for main_record in self: # 批量获取当前主记录下所有关联版本号,过滤空值并做去空格处理 all_versions = main_record.mdm_versions_ids.mapped('version') valid_versions = [v.strip() for v in all_versions if v and v.strip()] # 比对去重前后长度,存在重复则抛出错误 if len(valid_versions) != len(set(valid_versions)): raise ValidationError("版本号不允许重复,该版本已存在!") class MDMSolutionVersions(models.Model): _name = 'mdm.solutions.versions' _rec_name = 'version' mdm_class_id = fields.Many2one( 'mdm.solutions', string="MDM Class") version = fields.Char(string="Version", required=True)
逻辑说明
- 触发范围覆盖全场景:同时监听One2many字段本身、One2many关联行的version字段,新增/删除关联行、修改已有行版本号、从子表入口直接绑定主记录都会触发校验
- 自动覆盖两类重复场景:同一次操作提交的多条新增记录之间版本号重复、新增记录版本号和数据库已存的历史版本号重复
- 用ORM内置的
mapped()方法批量取字段值,避免逐行遍历的性能损耗,同时解决原代码取值错误的问题 - 自动过滤空值、处理版本号前后空格的输入误差,减少误判
内容的提问来源于stack exchange,提问作者for-loop
相关产品推荐
相关产品推荐

