「迁移是可逆的」到底可逆到什么程度?RunPython 不写反向会怎样?删除字段再回退,数据回来了吗?这篇把每种情形都真的回退一遍。
migrate lab 0001 → django.db.migrations.exceptions.IrreversibleError: Operation <RunPython <function Migration.<lambda> at 0x10b023b60>> in 加 RunPython.noop 作为 reverse_code: → ['Unapplying lab.0002_data... OK']
没有反向就不能回退,这是好事:强迫你想清楚。确实不需要反向时,写 RunPython.noop 明确表态。
正向后: [('KEEP',)]
反向(noop)后: [('KEEP',)] ← 数据没有还原Django 只负责在回退时调用你的反向函数,不验证它撤销了正向做的事。
加列后把 extra 改成 99: [('KEEP', 99)]
删列后: [(1, 'KEEP')]
回退「删列」之后(列回来了): [('KEEP', 7)] ← 数据是 default(7),不是删除前的 99结构可以回退,数据不能。所以在生产环境「回退迁移」不是备份的替代品。
删除前行数: [(1,)] 删除模型后表还在吗(0=不在): [(0,)] 回退 DeleteModel 后:表在吗(1=在) [(1,)] 行数 [(0,)]
同上。要保留数据,回退之前必须先备份。