pin_drop当前位置:知识文库 ❯ 图文

Django Migration迁移详解 - 数据库版本控制完整指南

Django Migration迁移详解 - 数据库版本控制指南

一、Migration概述

Migration(迁移)是Django的数据库版本控制系统,用于将Model的定义变更同步到数据库结构中。通过makemigrations命令生成迁移文件,再通过migrate命令执行迁移。Django会跟踪数据库的当前状态,支持向前执行和回滚操作。

迁移系统是团队协作和项目部署中的核心工具。每次Model变更(添加字段、修改类型、新增模型等)都应生成迁移文件,并将其纳入版本控制,确保团队成员和不同环境(开发、测试、生产)的数据库结构保持一致。

小贴士

Django会为每个应用自动创建migrations/目录来存放迁移文件,其中__init__.py使其成为Python包,0001_initial.py是初始迁移文件。

二、基本命令语法

以下是Migration最常用的四个命令:

代码示例

# 创建迁移文件 - 检测Model变更并生成迁移脚本
python manage.py makemigrations [app_label]

# 执行迁移 - 将未应用的迁移应用到数据库
python manage.py migrate [app_label] [migration_name]

# 查看迁移状态 - 显示已应用和未应用的迁移
python manage.py showmigrations [app_label]

# 生成SQL - 显示迁移对应的SQL语句(不执行)
python manage.py sqlmigrate app_label migration_name

三、参数详解与迁移操作

makemigrations 常用参数

参数 说明
app_label 指定为某个应用生成迁移
--name 自定义迁移文件名称
--empty 创建空的迁移文件(用于数据迁移)
--no-input 非交互模式,自动使用默认值

migrate 常用参数

参数 说明
app_label 只执行指定应用的迁移
migration_name 回滚到指定迁移版本(支持前缀匹配)
--fake 标记为已执行,但不实际执行SQL
--run-syncdb 同步创建没有迁移的表

迁移操作类型

操作类型 说明
CreateModel 创建新模型(表)
DeleteModel 删除模型(表)
AddField 添加字段
RemoveField 删除字段
AlterField 修改字段属性
RenameField 重命名字段
AddIndex 添加数据库索引
RunPython 执行Python代码(数据迁移)
RunSQL 执行原始SQL语句

迁移文件结构

代码示例

from django.db import migrations, models

class Migration(migrations.Migration):
    # 依赖的前置迁移
    dependencies = [
        ('app', '0001_initial'),
    ]

    # 要执行的操作列表
    operations = [
        migrations.AddField(
            model_name='article',
            name='subtitle',
            field=models.CharField(max_length=200, null=True),
        ),
    ]

四、实战代码示例

示例1:基本迁移流程

以下演示了从修改Model到执行迁移的完整流程:

代码示例

# 第一步:在 models.py 中添加新字段
# models.py: article 模型添加 subtitle 字段
# subtitle = models.CharField(max_length=200, blank=True)

# 第二步:生成迁移文件
python manage.py makemigrations

输出:

代码示例

Migrations for 'blog':
  blog/migrations/0002_article_subtitle.py
    - Add field subtitle to article

代码示例

# 第三步:查看迁移将执行的SQL
python manage.py sqlmigrate blog 0002

输出(以SQLite为例):

代码示例

ALTER TABLE "blog_article" ADD COLUMN "subtitle" varchar(200) NOT NULL DEFAULT '';

代码示例

# 第四步:执行迁移
python manage.py migrate

输出:

代码示例

Running migrations:
  Applying blog.0002_article_subtitle... OK

五、数据迁移详解

数据迁移用于在迁移过程中操作数据(如初始化默认数据、数据格式转换等)。通过--empty创建空迁移文件,然后编写RunPython操作。

代码示例

# 创建空迁移文件
python manage.py makemigrations --empty blog --name populate_categories

代码示例

# blog/migrations/0003_populate_categories.py
from django.db import migrations

def create_default_categories(apps, schema_editor):
    """正向迁移:创建默认分类"""
    # 注意:使用apps.get_model()而不是直接导入
    Category = apps.get_model('blog', 'Category')
    categories = ['Python', 'Django', 'JavaScript', '数据库']
    for name in categories:
        Category.objects.get_or_create(name=name)

def reverse_categories(apps, schema_editor):
    """反向迁移:删除创建的分类"""
    Category = apps.get_model('blog', 'Category')
    Category.objects.filter(
        name__in=['Python', 'Django', 'JavaScript', '数据库']
    ).delete()

class Migration(migrations.Migration):
    dependencies = [
        ('blog', '0002_article_subtitle'),
    ]

    operations = [
        migrations.RunPython(
            create_default_categories,
            reverse_categories
        ),
    ]

关键注意:在数据迁移中必须使用apps.get_model()获取模型,而不是直接导入。因为迁移文件可能在任何时间点执行,apps参数提供了当时模型的历史版本。

示例3:迁移回滚和管理

代码示例

# 查看迁移状态([X]表示已应用,[ ]表示未应用)
python manage.py showmigrations blog

输出:

代码示例

blog
 [X] 0001_initial
 [X] 0002_article_subtitle
 [ ] 0003_populate_categories

代码示例

# 回滚到指定迁移版本(取消0003的应用)
python manage.py migrate blog 0002

# 假执行(仅标记为已执行,不运行SQL)
python manage.py migrate --fake blog 0003

# 前进到最新迁移
python manage.py migrate blog

六、实际应用场景

  • 开发过程中添加新字段:每次修改Model后执行makemigrations和migrate,保持数据库同步

  • 数据迁移初始化默认数据:使用RunPython操作在迁移时创建默认分类、系统配置等基础数据

  • 部署时执行迁移:CI/CD流程中在代码部署后自动执行migrate,同步生产数据库结构

迁移操作对比

操作 命令 说明
生成迁移 makemigrations 检测Model变更生成迁移文件
执行迁移 migrate 将迁移应用到数据库
查看状态 showmigrations 显示已应用和未应用的迁移
查看SQL sqlmigrate 查看迁移对应的SQL语句
回滚 migrate app 0001 回滚到指定迁移版本
假执行 migrate --fake 标记为已执行但不运行SQL

七、注意事项

注意:修改Model后务必执行makemigrations和migrate,否则数据库不会更新,运行时会出现字段不存在的错误。

注意:迁移文件应纳入版本控制(Git),团队成员共享。不要将迁移文件加入.gitignore。

注意:删除迁移文件前确保已回滚,否则会导致数据库状态与迁移文件不一致,后续迁移可能失败。

注意:生产环境执行迁移前建议先备份数据库,以防迁移失败导致数据丢失。

注意:添加非空字段到已有表时,需要提供默认值(default=xxx)或允许为空(null=True),否则makemigrations会交互式询问默认值。

八、练习题

练习1

创建一个Article模型,执行初始迁移,然后添加一个新字段subtitle,再次生成并执行迁移。使用sqlmigrate查看生成的SQL语句。

练习2

编写一个数据迁移,为Category表插入3条默认分类数据(如"技术"、"生活"、"学习"),并实现完整的回滚函数。


常见问题

makemigrations和migrate有什么区别?

makemigrations检测Model的变更并生成迁移文件(Python脚本),不修改数据库;migrate读取未执行的迁移文件并在数据库中执行对应的SQL语句,实际修改数据库结构。

--fake参数的使用场景是什么?

--fake用于标记迁移为已执行但不实际运行SQL。常见场景:手动导入数据库后需要同步迁移状态、第三方库迁移冲突时跳过某些迁移、手动执行了SQL后更新迁移记录。

数据迁移中为什么要用apps.get_model()?

因为迁移可能在任何时间执行(包括回滚),apps.get_model()获取的是迁移执行时刻的模型历史版本,而不是当前最新的Model定义。直接使用导入的Model可能导致字段不存在或类型不匹配的异常。

如何合并多个迁移文件?

使用python manage.py makemigrations --merge app_label可以合并同一应用中存在分支的迁移。注意:合并不减少迁移文件数量,只是解决分支冲突。如果要精简迁移文件,需要使用squashmigrations。

迁移失败后如何修复?

首先使用showmigrations查看失败状态,然后通过migrate回滚到上一个成功版本。修复Model或迁移文件后重新生成并执行。如果是数据不一致导致,可能需要手动修复数据库后使用--fake标记。

标签: Django Migration 数据库迁移 makemigrations 数据迁移 版本控制

本文涉及AI创作

内容由AI创作,请仔细甄别

list快速访问

上一篇: Django ORM查询详解 - 数据库操作与优化完整指南 下一篇: Django静态文件管理教程:STATIC配置、collectstatic与Nginx部署

poll相关推荐