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 的迁移系统!如果还有疑问,欢迎留言讨论!💬

相关推荐
TDengine (老段)2 小时前
TDengine GROUP BY 与 PARTITION BY 使用及区别深度分析
大数据·开发语言·数据库·物联网·时序数据库·tdengine·涛思数据
IT教程资源D2 小时前
[N_093]基于springboot,vue的宠物商城
mysql·vue·前后端分离·宠物商城·springboot宠物商城
在风中的意志2 小时前
[数据库SQL] [leetcode-197] 197. 上升的温度
数据库·sql
啊吧怪不啊吧2 小时前
从单主机到多主机——分布式系统的不断推进
网络·数据库·redis·分布式·架构
老华带你飞2 小时前
电影购票|基于java+ vue电影购票系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot
老华带你飞2 小时前
宠物管理|基于java+ vue宠物管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·宠物
IT教程资源C2 小时前
(N_093)基于springboot,vue的宠物商城
mysql·vue·前后端分离·宠物商城·springboot宠物商城
鸽芷咕3 小时前
告别适配难题:Oracle 迁移 KingbaseES SQL 语法快速兼容方案
数据库·sql·oracle·金仓数据库
VX:Fegn08954 小时前
计算机毕业设计|基于springboot + vue智慧医药系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·课程设计