Django 迁移系统全指南:从模型到数据库的魔法之路

Django 迁移系统全指南:从模型到数据库的魔法之路

前言

你是否曾经遇到过这样的困扰:写好了一个 Python 的 models.py 文件,却发现不知道怎么在数据库中创建对应的表?或者修改了模型定义后,手动去数据库改表结构改得焦头烂额?

别担心,Django 的迁移系统就是为了解决这个问题而生的!今天我们就来深入了解一下这个强大的工具。


一、什么是 Django 迁移系统?

Django 迁移系统是一个自动化的数据库版本控制系统,它可以:

  • 📊 自动检测模型变化
  • 📝 生成迁移文件记录变化历史
  • 🚀 自动执行 SQL 来更新数据库

简单来说,你只需要写 Python 代码,剩下的事情 Django 都帮你搞定!


二、核心概念:两个命令

2.1 python manage.py makemigrations - 施工图纸

这个命令负责检测模型变化 并生成迁移文件。

python 复制代码
# apps/students/models.py
class Student(models.Model):
    name = models.CharField(max_length=100)
    age = models.IntegerField()  # 假设这是我们新增的字段

运行命令后:

bash 复制代码
$ python manage.py makemigrations

Migrations for 'students':
  apps/students/migrations/0002_add_age_field.py
    - Add field age to student

Django 会在 apps/students/migrations/ 目录下生成一个新的 Python 文件:

python 复制代码
# 0002_add_age_field.py
from django.db import migrations, models

class Migration(migrations.Migration):
    dependencies = [
        ('students', '0001_initial'),
    ]
    
    operations = [
        migrations.AddField(
            model_name='student',
            name='age',
            field=models.IntegerField(),
        ),
    ]

⚠️ 注意 :这个命令不会修改数据库,它只是准备了"施工图纸"。


2.2 python manage.py migrate - 真正施工

这个命令负责执行迁移文件 并修改数据库。

bash 复制代码
$ python manage.py migrate

Running migrations:
  Applying students.0002_add_age_field... OK

Django 会读取刚才生成的迁移文件,执行相应的 SQL:

sql 复制代码
ALTER TABLE students_student ADD COLUMN age INT;

并且会在 django_migrations 表中记录这个迁移已经被应用,防止重复执行。


三、两者的关系

可以用一个简单的类比来理解:

复制代码
┌─────────────────────────────────────────────────────────┐
│  makemigrations = 编写施工图纸                            │
│  (检测模型变化,生成迁移文件)                              │
└──────────────────────┬──────────────────────────────────┘
                       ↓
┌─────────────────────────────────────────────────────────┐
│  migrate = 按照图纸施工                                   │
│  (执行 SQL,修改数据库)                                   │
└─────────────────────────────────────────────────────────┘

四、完整的工作流程

场景:为学生表添加性别字段

第一步:修改模型
python 复制代码
# apps/students/models.py
class Student(models.Model):
    name = models.CharField(max_length=100, verbose_name='姓名')
    age = models.IntegerField(verbose_name='年龄')
    gender = models.CharField(
        max_length=10, 
        choices=[('male', '男'), ('female', '女')],
        default='male',
        verbose_name='性别'
    )  # 新增字段
第二步:生成迁移文件
bash 复制代码
$ python manage.py makemigrations

Migrations for 'students':
  apps/students/migrations/0003_add_gender_field.py
    - Add field gender to student
第三步:应用迁移
bash 复制代码
$ python manage.py migrate

Running migrations:
  Applying students.0003_add_gender_field... OK
第四步:查看结果
sql 复制代码
mysql> DESCRIBE students_student;
+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| id    | bigint       | NO   | PRI | NULL    | auto_increment |
| name  | varchar(100) | NO   |     | NULL    |                |
| age   | int          | NO   |     | NULL    |                |
| gender| varchar(10)  | NO   |     | male    |                |
+-------+--------------+------+-----+---------+----------------+

搞定!数据库表已经自动更新了!


五、Django 会自动做什么?

✅ Django ORM 自动处理的:

操作 示例 生成的 SQL
创建表 创建 Student 模型 CREATE TABLE
添加字段 新增 gender 字段 ALTER TABLE ADD COLUMN
修改字段 修改 name 字段长度 ALTER TABLE MODIFY COLUMN
删除字段 删除 age 字段 ALTER TABLE DROP COLUMN
创建索引 index=True CREATE INDEX
外键关系 ForeignKey FOREIGN KEY
多对多 ManyToManyField 自动创建中间表

❌ Django 不会做的:

  • 创建数据库本身 (需要手动执行 CREATE DATABASE)
  • 删除数据库
  • 数据库的备份和恢复

六、典型场景示例

场景 1:项目初始化

bash 复制代码
# 1. 创建数据库(手动做一次)
mysql -u root -p
CREATE DATABASE myproject CHARACTER SET utf8mb4;
exit;

# 2. 配置 settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'myproject',
        'USER': 'root',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '3306',
    }
}

# 3. 运行迁移(创建所有表)
python manage.py migrate

场景 2:开发过程中修改模型

bash 复制代码
# 修改 models.py 后
python manage.py makemigrations  # 检测变化
python manage.py migrate         # 应用到数据库

场景 3:团队协作

bash 复制代码
# 同事 A 修改了模型并提交代码
git pull

# 同事 B 拉取代码后
python manage.py makemigrations  # 检查是否有新迁移
python manage.py migrate         # 应用迁移

七、常见问题与解决方案

Q1: 如果数据库表已经存在怎么办?

情况 1:表是通过 SQL 手动创建的

bash 复制代码
# 先创建空迁移(不执行 SQL)
python manage.py makemigrations --empty

# 然后标记为已应用(告诉 Django 表已存在)
python manage.py migrate --fake

情况 2:数据库为空,直接运行迁移

bash 复制代码
python manage.py migrate

Q2: 如何查看迁移历史?

bash 复制代码
# 查看所有迁移
python manage.py showmigrations

# 查看某个应用的迁移
python manage.py showmigrations students

# 查看迁移将执行的 SQL(不实际执行)
python manage.py sqlmigrate students 0002

Q3: 如何撤销迁移?

bash 复制代码
# 撤销最后一次迁移(未应用)
python manage.py migrate students 0001

# 删除迁移文件(未应用)
rm apps/students/migrations/0002_add_age_field.py

Q4: 迁移冲突怎么办?

当多人同时修改同一个模型时可能出现冲突:

bash 复制代码
# 1. 创建新的迁移解决冲突
python manage.py makemigrations --merge

# 2. 应用迁移
python manage.py migrate

八、最佳实践

✅ 推荐做法:

  1. 每次修改模型后立即运行迁移

    bash 复制代码
    python manage.py makemigrations && python manage.py migrate
  2. 将迁移文件纳入版本控制

    bash 复制代码
    git add apps/*/migrations/*.py
    git commit -m "Add age field to Student"
  3. 不要手动修改迁移文件

    • 迁移文件由 Django 自动生成和依赖
    • 手动修改可能导致问题
  4. 生产环境部署前先在测试环境验证

    bash 复制代码
    # 测试环境
    python manage.py migrate --plan  # 查看将要执行的操作

❌ 避免的做法:

  1. 不要直接修改数据库表结构
  2. 不要删除已应用的迁移文件
  3. 不要在生产环境运行 makemigrations

九、总结对比表

特性 makemigrations migrate
作用 检测模型变化,生成迁移文件 执行迁移,修改数据库
修改数据库 ❌ 不修改 ✅ 执行 SQL
产生文件 ✅ 生成 .py 文件 ❌ 不产生文件
何时使用 修改 models.py 后 生成迁移文件后
执行次数 每次修改模型 每次有新迁移
可以撤销 可以删除未应用的迁移 可以回退到之前的版本

十、进阶技巧

1. 查看迁移计划(不执行)

bash 复制代码
python manage.py migrate --plan

2. 只运行特定应用的迁移

bash 复制代码
python manage.py migrate students

3. 回退到指定迁移

bash 复制代码
python manage.py migrate students 0001

4. 生成空的迁移(用于自定义操作)

bash 复制代码
python manage.py makemigrations --empty students

结语

Django 的迁移系统是一个强大而优雅的数据库管理工具,它让开发者能够专注于业务逻辑,而不是繁琐的 SQL 操作。

记住这两个命令:

bash 复制代码
python manage.py makemigrations  # 检测变化,生成迁移文件
python manage.py migrate         # 应用迁移,修改数据库

就这么简单!🎉


相关资源:


希望这篇博客能帮助你理解 Django 的迁移系统!如果还有疑问,欢迎留言讨论!💬

相关推荐
小蒜学长4 分钟前
基于Django+Vue喵汪联盟宠物领养系统的设计与实现(代码+数据库+LW)
后端·python·django·宠物领养系统·流程规范化
我不会起名字3226 分钟前
MySQL 8.0 迁移后 SQL 变慢:执行计划里 3 类被忽略的成本差异
mysql·explain·执行计划·索引下推·成本模型
楚识科技6 分钟前
信创环境下 OCR 部署实践:从麒麟系统到达梦数据库的全栈适配
数据库·ocr
飞浪纪元[FWC–FE]11 分钟前
Qt 构建排错实录:从 MSB 1009 到生成器选型
开发语言·数据库·qt
Paper数据分析-经管学术12 分钟前
1985-2026年中国低空经济专利明细数据库
数据库
RuoyiOffice12 分钟前
SpringBoot3 + openGauss:RuoYi Office 登录、流程发布与用印填报适配实战
java·数据库·spring boot·opengauss·信创
画中有画23 分钟前
时序数据库在物联网系统中的应用
数据库·物联网·时序数据库
Decay__7 小时前
05_MySQL 常用 SQL 大全 —— 诊断、管理、优化辅助 SQL 与三大系统库速查
运维·数据库·sql·mysql·架构
小徐不徐说11 小时前
C++ 接口与插件设计:从工厂注册到 Qt 动态插件
数据库·c++·qt·系统架构·程序设计
论文复现现场11 小时前
WRF、FEA 能用 L40S 加速吗?求解器检查、断点恢复与长期运行
java·数据库·算法·wrf·有限元分析·gpu计算·断点续算