Django自定义用户模型create_user邮箱归一化测试失败,normalize_email未生效
问题根因
- 第一,测试用例构造的测试输入完全不符合合法邮箱格式:传入的
'TEST.TES.com'字符串没有@分隔符,从Django源码逻辑看,normalize_email()只有在能通过拆分识别到邮箱的本地部分、域名部分时,才会对域名部分做小写转换;如果字符串内没有@符号,拆分失败会直接返回原输入字符串,不会执行任何归一化处理。 - 第二,测试的断言逻辑和
normalize_email()的实际工作规则不匹配:Django的normalize_email()仅会将@符号后的域名部分转为小写,不会修改@符号前的本地用户名部分的大小写,即便传入带@的合法邮箱,直接将存储的邮箱和全小写的原输入做相等对比,也会触发断言失败。
修复方案
根据业务对邮箱归一化的需求,分两种场景调整:
场景1:遵循Django默认的邮箱归一化规则(仅域名部分转小写)
- 修正测试用例的输入值,将无@的非法测试字符串替换为合法格式,比如
email = 'TEST@TEST.COM' - 修正测试断言逻辑,匹配
normalize_email()的实际输出:归一化后的邮箱会保留本地部分的原大小写,仅域名部分转小写,因此断言需要调整为self.assertEqual(user.email, 'TEST@test.com')
场景2:实现全邮箱小写归一化(不区分本地部分大小写)
- 调整自定义UserManager中
create_user方法的邮箱处理逻辑,在调用normalize_email()前先将邮箱字符串转为全小写,将原代码:
修改为:user = self.model(email=self.normalize_email(email), **extra_fields)user = self.model(email=self.normalize_email(email.lower()), **extra_fields) - 保留原有的测试断言即可正常运行,此时传入的邮箱会先完成全小写转换,再经过域名归一化处理,最终存储的值和
email.lower()完全一致。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

