为何Django调用create()时字段的unique=True约束未生效?
问题根因分析
- 你在Django Admin后台看到的报错属于表单层校验触发的提示,并非数据库层面抛出的约束错误:Django Admin基于ModelForm实现,会自动调用模型的
full_clean()方法完成唯一字段校验,所以重复值提交时会直接返回错误,不需要触达数据库。 - 最常见的触发原因是:你给
name字段加上unique=True属性后,没有执行makemigrations+migrate命令生成数据库层面的唯一索引。此时直接调用create()方法时,Django默认不会主动执行模型校验逻辑,数据库也没有对应约束拦截,所以重复值可以正常写入。 - 还有两类罕见场景也会导致该问题:
- 所用数据库的唯一约束支持被手动关闭,比如MySQL关闭了严格模式、SQLite开启了
ignore_constraint配置 - 自定义了模型的
save()方法,跳过了Django默认的约束检查逻辑
- 所用数据库的唯一约束支持被手动关闭,比如MySQL关闭了严格模式、SQLite开启了
修复方案
- 优先同步数据库约束:
运行如下命令生成并执行迁移,把唯一约束同步到数据库层:
python manage.py makemigrations python manage.py migrate
后续再调用create()写入重复值时,数据库会直接抛出IntegrityError错误拦截非法写入。
- 如果需要在代码层面提前拿到和Admin一致的友好报错,可以在保存前主动触发模型校验:
template = EmailTemplate(name='test_1') template.full_clean() # 重复值会在此处抛出ValidationError,和Admin报错逻辑一致 template.save()
内容的提问来源于stack exchange,提问作者alias51
相关产品推荐
相关产品推荐

