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

相关推荐
雨辰AI1 小时前
SpringBoot3 + 人大金仓读写分离 + 分库分表 + 集群高可用 全栈实战
java·数据库·mysql·政务
长城20241 小时前
关于MySql的ONLY_FULL_GROUP_BY问题
数据库·mysql·聚合列
常常有2 小时前
MySQL 底层执行原理:输入SQL语句到两阶段提交
数据库·sql·mysql
Mr. zhihao2 小时前
深入解析redis基本数据结构
数据结构·数据库·redis
m0_748839492 小时前
利用天正暖通CAD快速掌握风管数量统计的方法
数据库
随身数智备忘录2 小时前
什么是设备管理体系?设备管理体系包含哪些核心模块?
网络·数据库·人工智能
海市公约3 小时前
MySQL更新语句执行全流程:从Buffer Pool修改到二阶段提交
数据库·mysql·binlog·innodb·undo log·二阶段提交·update执行原理
颂love3 小时前
MySQL的执行流程
android·数据库·mysql
海市公约3 小时前
一条SQL查询的完整旅程:MySQL执行流程深度解析
sql·mysql·数据库优化·执行计划·连接器·查询缓存·sql执行原理
程序leo源4 小时前
Qt窗口详解
开发语言·数据库·c++·qt·青少年编程·c#