makemigrations 仅在修改模型(如增删字段、改related_name、加default)时需运行,它只生成迁移文件而不操作数据库;改视图或模板则无需执行。

makemigrations 什么时候该跑,什么时候不该跑
它只负责生成迁移文件,不碰数据库。你改了 models.py、删了字段、加了 default、改了 related_name,才需要它;但只是改了视图或模板,完全不用碰它。
常见错误现象:makemigrations 报 “No changes detected”,但你明明改了模型——大概率是没保存文件,或者改的是另一个 app 的模型却在错误目录下执行命令。
- 必须在项目根目录(有
manage.py的地方)运行 - 加
--dry-run可预览要生成哪些迁移,避免误提交空迁移 - 加
-n(--name)手动指定迁移名,比如python manage.py makemigrations --name add_is_active_to_user,比自动生成的0002_auto_20240512_1023.py更易读 - 如果改了模型又删了迁移文件,别手抖直接删
migrations/下所有文件——Django 会丢掉历史记录,后续migrate可能报错
migrate 执行失败最常见的三个原因
它才是真正操作数据库的指令,失败往往不是语法问题,而是状态不一致。
常见错误现象:django.db.migrations.exceptions.InconsistentMigrationHistory 或提示 “applied migration X.Y but not Y.Z”——说明数据库里记录的迁移状态和磁盘上文件对不上。
- 别在开发机上手工删数据库表或清空
django_migrations表,除非你清楚每条记录对应哪个迁移文件 - 多人协作时,有人提交了新迁移但你没拉,就先
git pull再migrate,否则可能卡在“找不到依赖迁移” -
migrate默认只向上迁移到最新,加app_name zero可回退到初始状态(慎用!生产环境绝对别试) - 如果中途出错中断,Django 通常会把事务回滚,但 SQLite 等不支持 DDL 事务的数据库可能留下半截表,得手动清理
迁移文件里 default 和 null=True 到底怎么配
这是新增非空字段时最常翻车的地方。Django 要求你明确告诉它:已有数据这列填啥?否则不知道怎么生成 SQL。
使用场景:给已有模型加一个新字段,比如 is_premium = models.BooleanField(),直接 makemigrations 就会弹出交互式提示。
- 选
1输入默认值(如True),Django 会在迁移里写死这个值,所有旧记录都设为True - 选
2退出并手动改模型,加上default=True或null=True,再重跑makemigrations -
null=True控制数据库是否允许 NULL,blank=True是表单校验层面的,别混;加null=True后,旧记录自动为 NULL,无需填默认值 - 如果字段类型是
DateTimeField,推荐用default=timezone.now(注意不带括号),而不是default=datetime.now(),否则所有记录时间戳一样
线上环境跑 migrate 要盯住什么
本地跑通不等于线上安全。Django 迁移不是原子操作,尤其涉及大表加索引、改字段类型时,可能锁表几秒甚至几分钟。
性能影响:PostgreSQL 对 ALTER COLUMN TYPE 会重写整张表;MySQL 5.7+ 在某些改类型场景也会锁表。
- 上线前先在同规格从库上试跑,观察慢查询日志和锁等待
- 加索引务必加
CONCURRENTLY(PostgreSQL),但makemigrations不会自动加,得手动编辑迁移文件,在operations里写RunSQL("CREATE INDEX CONCURRENTLY ...") - 别在高峰期执行迁移,特别是涉及
RemoveField或RenameField—— 它们底层仍是ALTER TABLE,不是元数据标记 - 迁移文件一旦提交到主干,就不能再修改内容(哪怕只是改个注释),否则不同人本地生成的哈希值不同,
migrate会拒绝执行
迁移不是黑盒,它生成的 SQL 才是真实影响数据库的东西。上线前打开迁移文件看看 operations 列表,比背命令重要得多。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











