Django执行migrate时报UNIQUE constraint failed: new__main_doctor.email错误
问题根因
- 你虽然回滚了
models.py的代码修改,但是之前生成的错误迁移文件main.0008_auto_20211014_0005没有被删除,每次执行migrate命令都会尝试应用这个迁移,所以报错会持续出现。 - 这个迁移本身失败的原因:你给
email字段加unique=True约束时,数据库里已经存在的Doctor数据中,要么有重复的email值,要么存在email为空的记录,唯一约束不允许这类数据存在,因此迁移执行失败。
解决步骤
情况1:开发环境,数据可以直接丢弃
这是成本最低的处理方式:
- 删除
main应用下migrations文件夹中除了__init__.py之外的所有迁移文件 - 删除项目根目录下的sqlite数据库文件(默认名称为
db.sqlite3) - 重新执行迁移命令即可:
python manage.py makemigrations python manage.py migrate
情况2:生产/测试环境,数据需要保留
需要先清理异常数据和错误迁移再操作:
- 先回滚到0008之前的正常迁移版本:
python manage.py migrate main 0007
注:上述命令中的
0007需要替换为你0008号迁移之前的最后一个正常迁移的编号
- 删除
main应用下生成的0008开头的错误迁移文件 - 进入Django shell处理现有异常数据:
python manage.py shell from main.models import Doctor # 查询email为空的记录 Doctor.objects.filter(email__isnull=True).count() # 查询有重复的email记录 from django.db.models import Count duplicate_emails = Doctor.objects.values('email').annotate(email_count=Count('email')).filter(email_count__gt=1) print(duplicate_emails)
- 将上述查询到的异常记录的
email字段修改为唯一、非空的合法值 - 重新修改
models.py的email字段为你需要的null=False, unique=True配置,再重新执行迁移:
python manage.py makemigrations python manage.py migrate
注意事项
如果执行makemigrations时Django提示需要给现有记录设置默认值,不要随意填写通用默认值,必须确保所有现有数据的email字段都满足唯一非空要求后再执行迁移,否则会再次触发相同的唯一约束错误。
内容的提问来源于stack exchange,提问作者Nitin Saini
相关产品推荐
相关产品推荐

