pin_drop当前位置:知识文库 ❯ 图文
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 常用参数
migrate 常用参数
迁移操作类型
迁移文件结构
代码示例
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,同步生产数据库结构
迁移操作对比
七、注意事项
注意:修改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标记。
本文涉及AI创作
内容由AI创作,请仔细甄别