bigywater.tech
Django · 56

--fake 与 --fake-initial

把已有的数据库接入 Django 迁移,或者迁移已经在库里手工做完了,就要用 --fake。这篇看它们各自「假装」了什么,以及最容易踩的两个坑:表存在但少列、fake 之后记录与实际不一致。

只查表
--fake-initial 判断的是初始迁移里的表是否存在,不核对列
只写记录
--fake 完全不碰数据库,记录与实际可以不一致
回退也是假的
migrate lab zero --fake 只删记录,表还在

已有表,直接 migrate

实测 · 本机执行输出
  migrate lab → django.db.utils.ProgrammingError: relation "lab_p" already exists
  django_migrations 里 lab 的记录: (无)

典型场景:把一个手工建表的库接入 Django,或者从另一个 Django 项目搬来表。

--fake-initial

实测 · 本机执行输出
   ['Applying lab.0001_initial... FAKED']
  记录: 0001_initial
   可以正常读写: 1
实测 · 本机执行输出
   ['Applying lab.0001_initial... FAKED']
  之后读写: ProgrammingError: column "age" of relation "lab_p" does not exist

它对「初始迁移」有效:CreateModel 的表已存在就跳过。它不比较列类型、不检查约束,所以之前要自己确认表结构与迁移一致。

--fake

实测 · 本机执行输出
  migrate lab --fake: ['Applying lab.0002_email... FAKED']
  记录: 0001_initial , 0002_email
  数据库里 lab_p 的列: id,name,age  ← 没有 email
  之后写入: ProgrammingError: column "email" of relation "lab_p" does not exist
实测 · 本机执行输出
   ['Unapplying lab.0002_email... FAKED', 'Unapplying lab.0001_initial... FAKED']
  记录: (无)  表 lab_p 还在吗: 1

适合「手工在库里做完了这个变更,补一条记录」。风险是记录与实际不符时,之后的查询才报错(而不是迁移时)。

分步演示:fake 的边界

--fake / --fake-initial
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / Python 3.14.7 / Django 6.1.1(默认用 SQLite,其它数据库会在文中注明),用 django.test.Client 或真实的本机服务器进程实测;计时用 time.perf_counter,数字每次运行会有小幅抖动。PostgreSQL 16.15(本机临时实例,端口 9432)
    • 没有验证:--fake-initial 对多个 app / 有外键依赖时的判断、--fake-initial 遇到 AddField 类初始迁移的列检查(文档说法不同版本不同,本文只测了 CreateModel)、fake 与 squashed migrations 的交互
    京ICP备2026067502号-1京公网安备11010502063487号