2 分钟阅读
Django 数据库迁移实战:makemigrations 和 migrate 背后的坑
更新说明:新增 Django 数据库迁移实践。
系列:Python Web 工程实践
- Python Web 项目配置管理:环境变量、.env 和生产配置怎么拆
- Python Web 项目如何连接数据库:SQLAlchemy、Django ORM、迁移怎么选
- Alembic 数据库迁移入门:表结构变更怎么安全上线
- Django 数据库迁移实战:makemigrations 和 migrate 背后的坑
- FastAPI 项目测试指南:pytest、TestClient、依赖覆盖怎么用
- Django 测试入门:Model、View、API 测试怎么写
- FastAPI 分层架构:router、service、repository 怎么拆
- PostgreSQL 基础:索引、事务、慢查询怎么理解
Django 的迁移很好用,也很容易让人放松警惕。makemigrations 能生成文件,migrate 能执行,但这不代表每一次结构变化都适合直接上线。
如果你刚开始用 Django,可以先看 Django 安装与使用指南 和 Django 进阶使用指南。
迁移文件记录的是变化过程
模型定义是当前状态,迁移文件记录的是从旧状态变到新状态的步骤。
python manage.py makemigrationspython manage.py migrate生成后不要急着提交,先看文件内容。
operations = [ migrations.AddField( model_name="article", name="status", field=models.CharField(default="draft", max_length=20), ),]这个迁移会给旧数据补默认值。小表没问题,大表就要考虑执行时间和锁。
字段改名要格外小心
Django 有时能识别字段重命名,有时会生成“删除旧字段 + 新增字段”。如果不看迁移文件,数据可能直接没了。
危险的迁移长这样:
migrations.RemoveField(model_name="article", name="name")migrations.AddField(model_name="article", name="title", field=models.CharField(max_length=120))如果确实是改名,应该生成或手动调整为:
migrations.RenameField( model_name="article", old_name="name", new_name="title",)大表新增字段怎么做
对大表新增非空字段,我更倾向于拆成几步:
- 先新增可为空字段
- 发布代码开始写入新字段
- 后台脚本补齐历史数据
- 再改成非空约束
这样比“一次迁移完成所有事”更稳。
status = models.CharField(max_length=20, null=True, blank=True)等数据补齐后,再改成:
status = models.CharField(max_length=20, default="draft")常用检查命令
查看迁移计划:
python manage.py showmigrationspython manage.py migrate --plan只生成迁移但不执行:
python manage.py makemigrations --dry-run --verbosity 3检查模型和迁移是否一致:
python manage.py makemigrations --check --dry-run提交迁移文件的习惯
我会把模型改动和迁移文件放在同一个提交里。提交前至少确认:
- 迁移文件名能看出目的
- 没有误删字段
- 默认值不会让大表迁移太慢
- 回滚路径不是空的
- 测试库能完整执行
总结
Django 迁移不是负担,它是线上数据结构的历史记录。认真看迁移文件,比事后修数据便宜得多。尤其是字段改名、大表默认值和删除操作,不要只相信自动生成结果。