Django应用部署到Heroku后迁移循环异常致崩溃求助
问题分析与解决:Heroku上Django迁移重复生成且状态矛盾的问题
问题现象
- 本地代码与Heroku仓库已同步,本地执行
makemigrations或migrate时无变更提示 - Heroku上执行
makemigrations users kits email,会重复生成完全相同的迁移文件,内容为修改historicalkit/historicaluser的Meta选项和history_date字段:python manage.py makemigrations users kits email Migrations for 'kits': apps/kits/migrations/0002_auto_20221209_1204.py - Change Meta options on historicalkit - Alter field history_date on historicalkit Migrations for 'users': apps/users/migrations/0002_auto_20221209_1204.py - Change Meta options on historicaluser - Alter field history_date on historicaluser - Heroku执行
migrate时,系统同时出现矛盾提示:既显示无迁移可应用,又提示**'kits'、'users'应用存在未反映到迁移中的变更**,最终导致Web应用崩溃:python manage.py migrate Operations to perform: Apply all migrations: admin, auth, contenttypes, email, kits, sessions, users Running migrations: No migrations to apply. Your models in app(s): 'kits', 'users' have changes that are not yet reflected in a migration, and so won't be applied. Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them.
核心原因
这类问题几乎都和django-simple-history(自动生成historical*模型的第三方库)的环境差异或迁移状态不匹配有关:
- 环境配置不一致:本地与Heroku的时区设置、
django-simple-history版本不同,导致自动生成的历史模型字段(如history_date的时区属性)或Meta选项存在隐性差异,Django每次检测都认为需要修改。 - 迁移状态哈希冲突:Heroku数据库的
django_migrations表中,已记录该迁移为已应用,但迁移文件的哈希值(Django判断迁移是否生效的标识)与本地不一致,导致系统陷入"已应用但仍有变更"的循环。 - 数据库表结构隐性差异:Heroku数据库中
historicalkit/historicaluser表的实际字段结构,与本地模型生成的预期结构存在差异,Django无法通过常规迁移修复,只能重复生成无效迁移。
解决步骤
1. 统一环境配置
- 确保本地和Heroku的
settings.py时区完全一致,例如都设置为:TIME_ZONE = 'UTC' - 检查
django-simple-history版本,本地与Heroku需完全相同,在requirements.txt中固定版本号,避免自动升级导致逻辑差异。
2. 修复迁移状态不匹配
- 先在Heroku上查看
django_migrations表的状态,确认目标迁移是否已被标记为应用:
进入shell后执行:heroku run python manage.py shellfrom django.db import connections cursor = connections['default'].cursor() cursor.execute("SELECT app, name FROM django_migrations WHERE app IN ('kits', 'users');") print(cursor.fetchall()) - 如果查询结果显示
0002_auto_20221209_1204已存在,手动标记该迁移为已应用(仅修改状态,不执行SQL):heroku run python manage.py migrate --fake kits 0002_auto_20221209_1204 heroku run python manage.py migrate --fake users 0002_auto_20221209_1204
3. 清除重复迁移文件
- 本地删除重复生成的迁移文件,提交到仓库后重新部署到Heroku:
rm apps/kits/migrations/0002_auto_20221209_1204.py rm apps/users/migrations/0002_auto_20221209_1204.py git add . git commit -m "Remove duplicate migration files" git push heroku main
4. 校验数据库表结构
- 登录Heroku数据库,查看
historicalkit和historicaluser的实际字段结构,与本地数据库对比:heroku pg:psql # 进入psql后执行 \d historicalkit; \d historicaluser; - 如果字段类型(如
history_date是否带时区)与本地不一致,手动调整数据库字段,或重新生成一次合规的迁移来统一结构。
内容的提问来源于stack exchange,提问作者RobertAKARobin
相关产品推荐
相关产品推荐

