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 分钟前
DAY61 IMX6ULL UART Serial Communication Practice
linux·服务器·网络·arm开发·数据库·驱动开发
二哈喇子!2 小时前
MySQL数据库概述
mysql
二哈喇子!6 小时前
MySQL数据更新操作
数据库·sql
二哈喇子!6 小时前
MySQL命令行导入数据库
数据库·sql·mysql·vs code
心动啊1216 小时前
SQLAlchemy 的使用
数据库
曾经的三心草8 小时前
redis-2-数据结构内部编码-单线程-String命令
数据结构·数据库·redis
二哈喇子!8 小时前
基于SSM框架的公交车查询系统的设计与实现
java·数据库·ssm
Coder_Boy_8 小时前
基于SpringAI的在线考试系统-智能考试系统-学习分析模块
java·开发语言·数据库·spring boot·ddd·tdd
阿杰 AJie8 小时前
MySQL 聚合函数总表(完整版)
数据库·mysql
玄同7659 小时前
Python「焚诀」:吞噬所有语法糖的终极修炼手册
开发语言·数据库·人工智能·python·postgresql·自然语言处理·nlp