Odoo Event模块注册触发utm_medium唯一约束冲突问题咨询
问题分析
为什么会触发唯一约束冲突?
- UTM媒介模型的
create方法通过utm.mixin的_get_unique_names做名称唯一性校验,但这个校验是大小写敏感的——它会把Email和email判定为两个不同的名称。 - 但你的数据库对
utm_medium.name字段采用了大小写不敏感的排序规则(比如PostgreSQL中使用大小写不敏感的collation),所以数据库层面会将Email和email视为同一个值,插入时触发唯一约束报错。
为什么Odoo没提前检查到?
因为Odoo代码里的校验逻辑是大小写敏感的,没把Email和email当成重复项,所以允许创建新记录,直到提交到数据库才被约束拦截。
修复方案
有两种实用的修复思路,按需选择:
思路一:让UTM名称校验大小写不敏感
在自定义模块里继承utm.medium,重写create方法,先检查是否存在大小写不同的同名记录,存在就直接复用,不创建新的:
from odoo import models, api class UtmMedium(models.Model): _inherit = 'utm.medium' @api.model_create_multi def create(self, vals_list): for vals in vals_list: name = vals.get('name') if name: # 用=ilike做大小写不敏感匹配 existing_medium = self.search([('name', '=ilike', name)], limit=1) if existing_medium: # 把要创建的名称替换成已存在的名称,避免冲突 vals['name'] = existing_medium.name return super().create(vals_list)
思路二:强制统一UTM名称的大小写
如果希望所有UTM媒介名称格式统一(比如全小写),可以在创建时强制转换,同时更新现有记录:
1. 代码修改(自定义模块)
from odoo import models, api class UtmMedium(models.Model): _inherit = 'utm.medium' @api.model_create_multi def create(self, vals_list): for vals in vals_list: if vals.get('name'): vals['name'] = vals['name'].lower() return super().create(vals_list)
2. 统一现有记录的大小写
备份数据库后,执行SQL语句更新现有记录:
UPDATE utm_medium SET name = lower(name);
紧急修复现有冲突
如果已经存在Email和email两条冲突记录,先清理:
- 备份数据库。
- 删除其中一条重复记录(比如保留
Email):
DELETE FROM utm_medium WHERE name = 'email';
- 检查并更新所有关联了被删除记录的单据(销售订单、活动注册等),把
utm_medium_id指向保留的记录。
注意事项
- 不要直接修改Odoo核心模块代码,用自定义模块继承扩展,方便后续版本升级。
- 这个问题通常是不同渠道生成的UTM名称大小写不一致导致的(比如邮件系统传
Email,网站表单传email),统一格式能从根源避免问题。
内容的提问来源于stack exchange,提问作者Ahrimann Steiner
相关产品推荐
相关产品推荐

