1. 迁移机制与底层原理

在 Django 中,ORM(Object-Relational Mapping)是连接模型(Model)和数据库结构的桥梁。Django 鼓励开发者通过编写 Python 类(模型)来定义业务数据结构,而不是手动创建数据库表。当模型发生变化时,如何将这些变化安全地同步到数据库?这就是 迁移系统(Migration System) 的职责。

Django 提供了两个核心命令来实现这一机制:

  • makemigrations:自动检测模型变更并生成迁移文件

  • migrate:将迁移文件中的变更应用到数据库中

什么是迁移(Migration)?

“迁移”是 Django ORM 用来管理数据库 schema(结构)变化的机制。它的核心思想是:

以版本化脚本的形式记录模型的每次变更,并确保这些变更可以一步步地、按顺序、安全地同步到数据库结构中。

每一个迁移文件(如 0001_initial.py)都表示一次变更的“快照”和“指令集”,包含:

  • 变更内容(如新增字段、删除模型)

  • 依赖关系(如依赖某次迁移)

  • 可执行的操作序列(operations)

迁移常见命令

命令说明应用场景
python manage.py makemigrations自动检测模型变更并生成新的迁移文件(记录变更指令)模型新增字段、修改字段、删除模型等操作后使用
python manage.py migrate执行迁移文件中的操作,应用到数据库本地或生产环境数据库更新结构时使用
python manage.py showmigrations显示所有 app 的迁移文件及其执行状态检查当前迁移执行情况,调试迁移问题
python manage.py sqlmigrate <app> <migration>查看某次迁移将执行的 SQL 语句审查实际执行的 SQL,避免意外删除数据
python manage.py migrate <app> zero将指定 app 的所有迁移回滚(还原到未迁移状态)重置数据库结构,仅用于测试或初始化
python manage.py migrate <app> <migration_name>回滚或迁移到某个特定迁移版本控制迁移步骤,手动回滚或追踪问题
python manage.py makemigrations --empty <app>生成一个空迁移文件(无自动检测变化)手动编写迁移(如 RunPythonRunSQL)的入口
python manage.py makemigrations --merge合并多个冲突的迁移文件分支合并后出现迁移冲突时使用
python manage.py migrate --fake <app> <migration>标记某个迁移为“已执行”,但不真正执行操作数据库已手动修改,跳过实际执行,仅记录状态
python manage.py migrate --fake-initial如果数据库中已有初始结构,跳过初始迁移操作数据库结构存在但未记录迁移时用于初始化

--fake和--fake-initial区别:

  • --fake标记迁移为已执行,但不实际执行数据库操作。常用于手动修改数据库结构后,同步 Django 记录。

  • --fake-initial:只对初始迁移(initial)文件起作用。若数据库中已存在对应表结构,会跳过执行迁移,仅标记为已迁移

--fake无条件标记为已迁移--fake-initial 是检测到表已存在时标记为已迁移,不重复创建表,如果表不存在,照常创建表

迁移命令背后的流程

makemigrations 工作流程

  1. 检测模型变化:Django 会加载当前所有模型定义,和上一次迁移文件中的“历史模型状态”进行对比。

  2. 生成变更指令:根据差异生成操作列表(如 AddField, RemoveField, AlterField 等)。

  3. 保存为迁移文件:把这些操作写入新的迁移文件中,路径通常是:yourapp/migrations/000X_*.py

Django 会在迁移文件中维护一个 state_operations 来表示“模型结构”,用于后续比对。

migrate 工作流程

  1. 读取数据库中已执行的迁移记录:Django 会读取特殊表 django_migrations

  2. 找出需要执行的迁移:即本地 migrations 文件夹中存在,但数据库未记录执行的迁移

  3. 逐个执行:迁移文件中的 operations 会被逐条执行(如 ALTER TABLE),并记录到 django_migrations

django_migrations 表的作用

该表是 Django 用于记录“数据库已完成哪些迁移”的关键数据结构,字段包含:

字段名说明
app应用名
name迁移文件名(不含后缀)
applied应用时间

这张表 并不代表数据库当前结构,它仅仅记录哪些迁移已被执行。数据库结构的真实状态取决于这张表 + 迁移脚本 + 数据库执行结果的三者一致性。 

迁移底层的 Operation 系统

每个迁移文件的 operations 是一个指令列表,继承自 django.db.migrations.operations.base.Operation,常见子类包括:

  • CreateModel:创建模型

  • AddField / RemoveField:字段变更

  • AlterField:字段属性修改

  • RunPython:执行自定义 Python 代码(如数据迁移)

  • RunSQL:执行原生 SQL(如重命名表等)

这些操作通过 MigrationExecutor 进行调度和执行,内部依赖 SchemaEditor 进行跨数据库后端兼容处理。

2. 常见错误分类与解决方案

Django 的迁移系统虽然强大,但在实际开发中,尤其是多人协作、频繁模型变更的场景中,迁移相关的报错比较常见。以下是开发中出现的问题及解决建议记录:

❌ 1. table already exists

表已存在

django.db.utils.OperationalError: (1050, "Table 'xxx' already exists")

常见场景 

你尝试运行migrate,报错说某张表已经存在。这通常出现在以下几种开发/部署场景中 

  • 手动在数据库中创建过表(如写了原生 SQL)

  • 还原了生产环境数据库结构,但本地仍执行初始迁移

  • 某个 app 的迁移记录丢失或未提交,但数据库中的表已经存在

问题本质:

Django 迁移系统默认假设自己会“从无到有”创建所有表。如果你跳过了创建记录、手动建了表或还原了旧数据,它在执行 CreateModel 操作时会检测到表已存在,从而报错。

换句话说:数据库中已经有表了,但 django_migrations 表中没有记录迁移已执行。 

✅ 解决方案:使用 --fake-initial

Django 为此场景提供了专门参数:

python manage.py migrate --fake-initial

含义是:如果数据库中已经存在初始表结构,就跳过初始迁移文件的执行,但仍然将迁移记录写入 django_migrations,以免后续迁移报错。

仅适用于“数据库中已有表结构”且“你确定结构与模型一致”的情况。

❌ 2. is applied before its dependency

迁移历史不一致

错误信息:

​django.db.migrations.exceptions.InconsistentMigrationHistory:
Migration <app>.<migration_name> is applied before its dependency <other_app>.<migration_name> on database 'default'.

常见场景:

将测试环境或生产环境中的完整数据库备份(含数据和表结构)导入本地开发环境后,执行 migrate 命令时抛出该错误。

本地和远程环境的迁移文件可能一致,但数据库中 django_migrations 表中的记录已经“走在前面”或出现不一致。

错误本质:

Django 通过 django_migrations 表记录哪些迁移已经在数据库中执行过。
但在某些情况下,如从测试环境复制数据库后:

  • 数据库结构已经更新到较新的状态(如执行了 0005_auto_xxxx

  • 本地代码中的迁移文件还停留在较早状态(如只有到 0003

当你在本地执行 migrate 时,Django 会发现 数据库中“先执行”了某个迁移,但它依赖的迁移在本地尚未执行,于是抛出 InconsistentMigrationHistory 异常。

通用解决方案(推荐用于开发/测试环境)

清空迁移记录,让 Django 以 --fake 的方式重新记录当前状态,而不实际执行数据库操作

步骤如下:

  • 清空 django_migrations 表:

    ⚠️ 此操作不会影响业务数据,仅清除迁移记录。

-- MySQL / PostgreSQL:
TRUNCATE TABLE django_migrations;-- SQLite:
DELETE FROM django_migrations;
  • 确保本地代码迁移文件完整、和数据库结构对应:

    ✅ 推荐:使用与数据库导出时相同的 Git 分支代码,并保留 migrations/ 目录。

  • 重新 fake 所有迁移(跳过实际执行,仅登记记录): 

python manage.py migrate --fake

🔐 注意事项:

  • 不要在生产环境这样操作,否则迁移记录丢失,后续无法增量执行迁移。

  • 清空 django_migrations 后,数据库和模型之间的状态需完全一致,否则你跳过的是未正确应用的变更,可能引发更严重的问题。 

❌ 3. non-nullable field without a default

添加非空字段时执行makemigrations报错 

错误信息:

You are trying to add a non-nullable field 'xxx' to <Model> without a default

 常见场景:
在已有数据的模型中新增一个字段,未设置null(默认为null=False)且未指定默认值:

# 原有模型
class Product(models.Model):name = models.CharField(max_length=100)# 修改后(会报错)
class Product(models.Model):name = models.CharField(max_length=100)status = models.IntegerField()  # 新增字段未指定 default

原因分析:
数据库中的旧数据没有该字段,Django 不知道用什么值填充现有记录。 

解决方案: 

方法一:设置默认值

status = models.IntegerField(default=0)

方法二:允许为空

status = models.IntegerField(null=True, blank=True)

方法三:在迁移时指定默认值(Django 提示时输入) 

方法四:使用 RunPython 手动填充旧数据,再移除默认值(推荐用于正式项目) 

❌ 4. Duplicate column name

字段重复导致migrate失败

错误信息: 

django.db.utils.OperationalError: (1060, "Duplicate column name 'xxx'")

常见场景:
迁移文件被误删或修改,模型与数据库结构不一致,重新执行迁移导致字段重复。

原因分析:
数据库中已有字段,但迁移记录(django_migrations)中并未记录此字段的创建,Django 尝试重新创建列。

解决方案:

  • 核对数据库中实际结构和模型定义,确认字段是否已存在

  • 避免手动修改数据库结构;如果修改,必须确保迁移状态同步

  • 使用 migrate --fake 标记迁移已执行,跳过实际操作:        

python manage.py migrate yourapp 0001 --fake

❌ 5. Unknown column 'xxx' in 'field list'

删除字段后未清理数据依赖导致迁移失败 

错误信息:

django.db.utils.OperationalError: (1054, "Unknown column 'xxx' in 'field list'")

常见场景:
删除模型字段后,项目代码或数据迁移脚本中仍有对该字段的引用。

原因分析:
字段已从模型中移除,但数据库中仍存在引用字段的旧代码或旧 SQL。

解决方案:

  • 全局搜索项目代码中是否还有 xxx 字段的使用

  • 若使用 RunPython 写了数据迁移脚本,需改为先清数据后删字段

  • 对于依赖字段的查询逻辑,也要在迁移之前调整逻辑

❌ 6. conflicting migrations

多人协作导致makemigrations冲突

错误信息:

Conflicting migrations detected; multiple leaf nodes

常见场景:
两名开发者分别在不同分支对同一个 app 做了迁移,合并后造成迁移分叉。

原因分析:
迁移文件是线性依赖的,两个迁移文件若没有互相引用,就形成冲突。

解决方案:
使用 --merge 合并迁移:

python manage.py makemigrations --merge

Django 会生成一个新的迁移文件,合并两个冲突迁移(开发者需判断操作顺序)。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/87116.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/87116.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/87116.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SuperGlue:使用图神经网络学习特征匹配

摘要 本文提出了 SuperGlue&#xff0c;一种神经网络&#xff0c;用于通过联合寻找对应关系并排除不可匹配点来匹配两组局部特征。匹配结果通过求解一个可微的最优传输问题来估计&#xff0c;该问题的代价由一个图神经网络预测。我们引入了一种基于注意力的灵活上下文聚合机制…

ssh -T git@github.com失败后解决方案

这个错误表示你的 SSH 连接无法到达 GitHub 服务器。以下是详细解决方案&#xff0c;按照优先级排序&#xff1a; 首选解决方案&#xff1a;使用 SSH over HTTPS&#xff08;端口 443&#xff09; 这是最有效的解决方案&#xff0c;因为许多网络会阻止 22 端口&#xff1a; …

从苹果事件看 ARM PC市场的未来走向

最近&#xff0c;苹果宣布部分搭载 Intel 处理器的 Mac 不再支持最新的 macOS 系统更新&#xff0c;这一消息犹如一颗石子投入平静湖面&#xff0c;激起层层涟漪。它不仅让 Intel 芯片在 Mac 产品线上彻底成为历史&#xff0c;也促使我们重新审视 PC 行业的发展脉络&#xff0c…

vue + element ui 实现超出宽度展示..,鼠标移入显示完整内容

vue element ui 实现超出宽度展示…&#xff0c;鼠标移入显示完整内容 代码理念&#xff1a; 当高度大于对应行数的高度 则说明需要展示"…" 子组件 <template><div class"tooltip"><div ref"tooltipRef" :class"[tooltip…

HarmonyOSNext应用无响应全解析:从机制到实战的卡死问题排查

HarmonyOSNext应用无响应全解析&#xff1a;从机制到实战的卡死问题排查 ##Harmony OS Next ##Ark Ts ##教育 本文适用于教育科普行业进行学习&#xff0c;有错误之处请指出我会修改。 喂喂喂&#xff01;应用卡成PPT了&#xff1f;点啥都没反应&#xff1f;别慌&#xff01…

git 迁移之获取原库所有分支

以下是一个安全的 Bash 脚本&#xff0c;用于将远程 Git 仓库的所有分支检出到本地&#xff08;自动跳过已存在的分支&#xff09;&#xff1a; #!/bin/bash# 获取所有远程分支&#xff08;排除 HEAD&#xff09; remote_branches$(git branch -r | grep -v HEAD\|->)# 循环…

设计模式 | 适配器模式

适配器模式&#xff08;Adapter Pattern&#xff09; 是结构型设计模式中的连接器大师&#xff0c;它允许不兼容接口的类能够协同工作。本文将深入探索适配器模式的核心思想、实现技巧以及在C中的高效实践&#xff0c;解决现实开发中的接口兼容性问题。 为什么需要适配器模式 …

RTL 级机器人电机控制器的 FPGA 设计

借助Verilog&#xff0c;在FPGA中实现了带编码器的两台电机的电机控制系统的RTL级设计。 介绍 借助硬件描述语言 (HDL) Verilog 和 AMD Vivado 设计套件&#xff0c;在 AMD Spartan-7 FPGA 中实现带编码器的两个电机的控制器系统的 RTL 设计。 在这个项目中&#xff0c;使用了搭…

4_Flink CEP

Flink CEP 1、何为CEP&#xff1f; CEP&#xff0c;全称为复杂事件处理&#xff08;Complex Event Processing&#xff09;&#xff0c;是一种用于实时监测和分析数据流的技术。 CEP详细讲解&#xff1a; CEP是基于动态环境的事件流的分析技术&#xff0c;事件是状态变化&am…

容器基础知识2-K8s 和 Docker 的关系与管理逻辑详解

K8s 和 Docker 的关系与管理逻辑详解 一、先搞懂&#xff1a;Docker 和 K8s 分别是做什么的&#xff1f; Docker&#xff08;容器工具&#xff09;&#xff1a;好比「集装箱工厂」&#xff0c;负责把应用和依赖打包成标准化容器&#xff08;类似集装箱&#xff09;&#xff0…

QT MaintenanceTool 登录无法找到 QtAccount 凭据

亲测有效&#xff1a;QT6 Maintenance Tool 登录问题_qt6 maintenancetool-CSDN博客 将ini这个配置文件移出文件夹后&#xff0c;在切换自己账户登录即可

华为云Flexus+DeepSeek征文|利用华为云一键部署 Dify 平台并接入 DeepSeek 大模型,构建长篇文章生成助手

目录 前言 1 华为云一键部署 Dify 平台 1.1 华为云 Dify 平台介绍 1.2 部署过程介绍 1.3 登录 Dify 平台 2 接入华为云 ModelArts Studio 中的 DeepSeek 大模型 3 构建长篇文章生成助手 3.1 简要介绍长篇文章生成助手 3.2 开始节点 3.3 生成标题和大纲&#xff08;LL…

js的一些基础概念总结

1.变量声明 首先js变量声明有三种&#xff0c;var&#xff0c;const&#xff0c;let&#xff0c;这三种变量声明中我们第一优先使用const&#xff0c;需要改变这个值的时候我们用ley&#xff0c;var是尽量不去使用。 那么我们现在来总结一下三种声明变量的区别。首先是var let …

防 XSS和CSRF 过滤器(Filter)

会话管理存在问题&#xff1a; 1.服务集群部署或者是分布式服务如何实现会话共享 2.会话的不同存储地方的安全性问题 答&#xff1a; 会话共享 可以使用后端集中管理(redis)或者客户端管理 &#xff08;jwt&#xff09;&#xff1b; 存储安全性 这个还真的没有太好的方式&…

鸿蒙容器组件 WaterFlow、FlowItem解析:动态瀑布流布局实践

一、引言&#xff1a;不规则布局的智能化解决方案 在图片社交、电商导购、资讯聚合等现代应用场景中&#xff0c;瀑布流布局以其灵活的空间利用率和自然的视觉流动感成为界面设计的重要选择。鸿蒙提供的 WaterFlow 与 FlowItem 组件&#xff0c;通过智能布局算法与声明式语法&…

概率密度基本概念

概率密度&#xff08;Probability Density&#xff09;是概率论中用于描述随机变量分布的一种方式&#xff0c;特别适用于连续随机变量。它并不是一个概率值&#xff0c;而是表示单位范围内的概率大小或“浓度”。更具体地说&#xff0c;概率密度表示在某个特定值附近&#xff…

10-1 MySQL 索引优化与查询优化

10-1 MySQL 索引优化与查询优化 文章目录 10-1 MySQL 索引优化与查询优化1. 数据准备2. 索引失效案例2.1 索引字段&#xff1a;全值匹配最优2.2 索引字段&#xff1a;最佳左前缀法则2.3 主键插入顺序2.4 索引字段进行了&#xff1a;计算、函数、类型转换(自动或手动)导致索引失…

基于目标驱动的分布式敏捷开发

研究结论 风险对项目目标的影响 时间目标&#xff1a;需求管理不当&#xff08;如需求优先级不明确、多产品负责人需求冲突&#xff09;、架构变更导致的返工、跨站点协调问题&#xff08;如第三方依赖、通信基础设施不足&#xff09;是影响项目时间的主要风险因素。质量目标&…

高通手机跑AI系列之——穿衣试装算法

环境准备 手机 测试手机型号&#xff1a;Redmi K60 Pro 处理器&#xff1a;第二代骁龙8移动--8gen2 运行内存&#xff1a;8.0GB &#xff0c;LPDDR5X-8400&#xff0c;67.0 GB/s 摄像头&#xff1a;前置16MP后置50MP8MP2MP AI算力&#xff1a;NPU 48Tops INT8 &&…

opencv入门(5)图像像素的读写操作和算术运算

文章目录 1 图像遍历与修改1.1 使用数组1.2 使用指针 2 图像的算术运算2.1 一般算术操作2.2 算术API 1 图像遍历与修改 C中支持 数组遍历 和 指针方式遍历 1.1 使用数组 访问使用 image.at(row,col) 进行访问 如果是单通道灰度图&#xff0c;就使用image.at进行读取 如果是三…