Django自定义迁移后给模型加新字段触发列不存在错误如何解决
Django 迁移字段不存在报错解决方案
问题本质
报错的核心原因是自定义迁移直接引入了项目当前最新版本的模型类,没有使用Django迁移体系提供的历史版本模型。
迁移执行是按依赖顺序串行执行的:
- 002迁移运行时,003新增
config_data字段的迁移还未执行,数据库表中不存在该字段 - 直接导入的最新MyUser模型已经包含
config_data字段,ORM查询时会自动拼接所有字段的查询语句,最终触发字段不存在的报错
修复方案(适配双场景)
只需要修改002_custom_user_data.py文件,将直接引入模型的写法替换为通过apps.get_model获取历史版本模型即可,该方案对两种场景都兼容:
- 已经执行过002迁移的生产环境:Django会在
django_migrations表中记录已执行的迁移,修改后的002不会重复执行,直接运行python manage.py migrate即可正常跑完003迁移 - 全新空白数据库:执行002迁移时会自动获取对应版本的历史模型,该模型仅包含001初始化的字段,不会查询后续新增的
config_data字段,不会触发报错
修改后的002迁移完整代码
# Generated by Django 3.2.2 from django.db import migrations def create_user(apps, schema_editor): # 从迁移上下文获取对应版本的历史模型,不会包含后续新增字段 MyUser = apps.get_model('my_user', 'MyUser') # 修正原代码get_or_create返回值接收错误:该方法返回(实例, 是否创建)元组 user, _ = MyUser.objects.get_or_create(id=123) user.address = 'demo' user.save() def delete_user(apps, schema_editor): MyUser = apps.get_model('my_user', 'MyUser') MyUser.objects.filter(id=123).delete() class Migration(migrations.Migration): dependencies = [ ('my_user', '001_initial'), ] operations = [ migrations.RunPython(create_user, delete_user, elidable=True) ]
后续操作
修改完成后直接执行迁移命令即可:
python manage.py migrate
确认003迁移可以正常执行完成即可。
补充说明
所有Django自定义迁移的RunPython操作中,都不应该直接导入项目的最新模型,必须通过apps.get_model获取历史版本模型,避免后续模型迭代导致旧迁移执行失败,这是Django迁移的官方推荐最佳实践。
内容的提问来源于stack exchange,提问作者Akash Pagar
相关产品推荐
相关产品推荐

