Odoo开发:如何实现crm.project双字段组合的重复值校验并弹出警告
原代码存在的问题
- 取值键名错误:
vals是创建记录时传入的字段值字典,键名为字段本身的名称,原代码用crm.project.customer_id作为键取值,永远返回空值,后续校验逻辑完全失效。 - 校验逻辑拆分错误:原代码分别单独查询匹配客户的记录、匹配产品的记录,只要两个查询各自有结果就触发警告,会出现“库里存在一条客户A的记录、存在一条产品B的记录,但两条分属不同记录”的误触发场景,完全不符合“双字段组合完全匹配”的校验要求。
- 执行顺序错误:原代码先调用父类create方法将记录写入数据库后才执行校验,此时搜索结果会把刚写入的新记录本身算进去,逻辑顺序颠倒。
- 校验场景覆盖不全:仅重写create方法,用户在已有记录上修改客户、产品字段时,不会触发对应的重复组合校验,存在数据脏写的风险。
可直接运行的正确实现
校验核心逻辑:将客户、产品两个字段的条件放在同一个搜索域中,直接查询是否存在完全匹配该组合的存量记录,只要查到就触发警告。
from odoo.exceptions import UserError from odoo import api, fields, models, _ class CrmProject(models.Model): _name = 'crm.project' customer_id = fields.Many2one('res.partner','Customer') project_product_id = fields.Many2one('crm.project.product','Project Product') @api.model def create(self, vals): # 按原逻辑生成项目编号序列 vals['name'] = self.env['ir.sequence'].next_by_code('crm.project') # 执行真正的创建前先做重复组合校验 customer_id = vals.get('customer_id') project_product_id = vals.get('project_product_id') # 两个字段都有值时才做组合校验,避免空值场景误触发 if customer_id and project_product_id: # limit=1 只要查到一条匹配记录即判定重复,减少数据库查询开销 duplicate_record = self.search([ ('customer_id', '=', customer_id), ('project_product_id', '=', project_product_id) ], limit=1) if duplicate_record: raise UserError(_('The project has already been set before')) # 校验通过后执行创建动作 return super(CrmProject, self).create(vals) def write(self, vals): # 覆盖编辑场景的校验:取修改后两个字段的最终值,vals无传入值时取原记录的存量值 customer_id = vals.get('customer_id', self.customer_id.id) project_product_id = vals.get('project_product_id', self.project_product_id.id) if customer_id and project_product_id: # 搜索时排除当前正在编辑的记录本身,避免用户正常保存时被误判为重复 duplicate_record = self.search([ ('customer_id', '=', customer_id), ('project_product_id', '=', project_product_id), ('id', 'not in', self.ids) ], limit=1) if duplicate_record: raise UserError(_('The project has already been set before')) return super(CrmProject, self).write(vals)
实现效果说明
- 新建记录时:只有当传入的客户+产品组合和库里任意一条已有记录的组合完全一致时,才会弹出警告,和要求的匹配逻辑完全一致。
- 编辑记录时:如果修改两个字段后形成的组合和其他已有记录重复,也会被拦截,避免脏数据。
- 只要两个字段有任意一个为空,就不会触发校验,符合空值场景的业务逻辑。
内容的提问来源于stack exchange,提问作者Faiz
相关产品推荐
相关产品推荐

