Django 數據遷移全解析:makemigrations migrate 常見錯誤與解決方案

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進行讀取 如果是三…