makemigrations 是怎么知道你改了什么的?为什么改个 choices 也要生成迁移?改名为什么会问你一句「是不是改名」?这篇一次只改一处,把 14 种改动各跑一遍。
改动 检测到的操作 SQL 条数 新增字段(有 default) Add field stock to item 4 新增字段(null=True) Add field stock to item 1 新增字段(没有 default 也不许 NULL) Field 'stock' on model 'item' not migrated: it is im - max_length 20 → 50 Alter field name on item 4 字段类型 IntegerField → BigIntegerField Alter field price on item 4 只改 help_text(不影响数据库) Alter field price on item 0 只改 choices(不影响数据库) Alter field name on item 0 删除字段 Remove field note from item 1 字段改名 price → cost Remove field price from item; Add field cost to item 5 模型类改名 Item → Product Create model Product; Delete model Item 2 新增 Meta.indexes Create index lab_item_name_1e8c73_idx on field(s) na 1 新增 unique_together Alter unique_together for item (1 constraint(s)) 1 新增方法 / @property(纯 Python) (没有检测到变化) - 改 Meta.ordering Change Meta options on item 0
比较的对象是「所有迁移文件按顺序重放得到的状态」与「当前 models」——不是数据库。所以数据库被手工改过的部分它不知道(第 56 篇)。SQL 条数是 SQLite 的(它改列要重建表);PostgreSQL 上同样的改动通常更少。
--noinput: ['- Remove field price from item', '+ Add field cost to item'] 交互回答 y: ['~ Rename field price on item to cost'] | 提问原文: ["Was item.price renamed to item.cost (a IntegerField)? [y/N] Migrations for 'lab':"]
['- Remove field price from item', '+ Add field cost to item']
Django 无法区分「改名」和「删了一个再加一个同类型的」,于是交互式地问你。CI 里用 --noinput 或 --check 时它按「删除 + 新增」处理,这是数据丢失的来源。改名建议分两次提交:先改名(回答 y),再改类型。