Django模型改继承BaseModel后migrate外键约束报错
问题根因
迁移失败的核心原因是:给已存在历史数据的blooddiscard表新增status_master外键字段时,模型配置的默认值3在关联的Master_statusmaster表中不存在,触发了数据库外键约束校验,直接中断迁移流程。
解决方法
根据实际场景选对应方案即可:
方案1:最快修复(适合本地开发环境,允许补充基础数据)
- 先在
StatusMaster表中插入id=3的对应状态记录,执行命令进入Django shell:python manage.py shell - 在shell中执行以下代码插入记录(注意替换成项目中StatusMaster的实际导入路径,以及id=3对应的真实业务状态名称):
from Master.models import StatusMaster # 示例:如果id=3对应状态为"已作废",替换name字段的实际值即可 StatusMaster.objects.get_or_create(id=3, defaults={"name": "对应状态名称"}) - 退出shell后重新执行迁移命令即可成功:
python manage.py migrate
注意:因为模型中
status_master配置了default=3,后续新建BloodDiscard记录如果不传该字段值会默认关联id=3的状态,所以这条记录不要随便删除,否则后续新建数据也会触发外键错误。
方案2:无脏数据修复(推荐,适合不想插入无效基础数据的场景)
- 首先删除之前生成的未应用成功的问题迁移文件:直接删掉
Form/migrations/目录下的0018_auto_20220622_2322.py文件即可。 - 修改BaseModel中
status_master字段的配置,因为字段本身已经设置了null=True,临时去掉不存在的默认值,先保证迁移能顺利执行:class BaseModel(models.Model): created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) # 临时去掉default=3,保留空值允许配置 status_master = models.ForeignKey(StatusMaster,on_delete=models.SET_NULL,null=True, blank=True) - 重新生成迁移文件:
这时候因为新增字段允许为空,不需要手动填一次性默认值,会直接生成合法的迁移文件。python manage.py makemigrations - 执行迁移,这时候历史数据的
status_master字段会被填充为NULL,不会触发外键报错:python manage.py migrate - (可选业务处理)迁移成功后,进入Django shell批量给已有的BloodDiscard历史数据补全正确的状态关联值。
- (可选配置还原)如果需要给后续新建的记录配置默认状态,等确认StatusMaster表中存在对应id的状态记录后,再把
default=对应存在的id加回status_master字段配置,重新生成并执行迁移即可。
额外优化建议
当前BloodDiscard模型中自带的timestamp = models.DateTimeField(auto_now_add=True, blank=True)字段,和BaseModel提供的created_at字段功能完全重复,迁移完成后可以删掉这个冗余的timestamp字段,同步生成迁移即可,避免同一张表存储两个功能一致的创建时间字段。
内容的提问来源于stack exchange,提问作者mayank gupta
相关产品推荐
相关产品推荐

