本文目录导读:
在Django中执行数据迁移主要分两种情况:创建/修改模型后的结构迁移(如添加字段、改字段类型)和数据迁移(如批量修改现有数据内容),以下是详细执行步骤:
结构迁移(最常用)
这是修改数据库表结构的标准流程(比如新增一个 age 字段)。
修改 models.py
# models.py
class User(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField(null=True, blank=True) # 新加的字段
生成迁移文件
python manage.py makemigrations
- Django 会检测模型与数据库的差异,自动生成迁移文件(在
app/migrations/目录下,0002_user_age.py)。 - 注意:如果新增字段没有设默认值且不允许为空,会提示你输入默认值或设为
null=True。
执行迁移
python manage.py migrate
- 这会真正修改数据库表(添加
age列)。 - 会按顺序执行所有未应用的迁移文件(包括依赖的其他app迁移)。
数据迁移(处理已有数据)
当需要修改或填充现有数据时(给所有用户设置默认年龄为18),不能用结构迁移,而要用数据迁移。
创建一个空数据迁移文件
python manage.py makemigrations --empty yourappname
- 生成一个只包含
dependencies的空迁移文件。
编辑迁移文件,添加数据操作
# yourappname/migrations/0003_auto_xxx.py
from django.db import migrations
def set_default_age(apps, schema_editor):
User = apps.get_model('yourappname', 'User')
for user in User.objects.all():
user.age = 18
user.save(update_fields=['age'])
class Migration(migrations.Migration):
dependencies = [
('yourappname', '0002_...'), # 前一个迁移
]
operations = [
migrations.RunPython(set_default_age),
]
执行数据迁移
python manage.py migrate
- Django 会执行
RunPython中的函数,逐条更新数据。
常用命令速查
| 命令 | 作用 |
|---|---|
python manage.py showmigrations |
查看哪些迁移已应用(打[X]),哪些未应用 |
python manage.py migrate app_name 0001 |
回退到某个迁移版本(0001 是迁移文件名前缀) |
python manage.py migrate app_name zero |
撤销该app所有迁移(表会被删除!小心使用) |
python manage.py sqlmigrate app_name 0002 |
预览某个迁移对应的SQL语句(不执行) |
常见注意事项
新增必填字段且无默认值
如果新增字段 age = models.IntegerField() (不允许为空),执行 makemigrations 时Django会问:
You are trying to add a non-nullable field 'age' to user without a default...
此时你必须:
- 输入一个默认值(仅用于迁移时填充旧数据)
- 或者改为
null=True然后做数据迁移补数据
迁移冲突
多人协作时,如果别人也生了相同序号迁移文件(如两个人都做了 0002_xxx.py),执行 migrate 会报错,解决方案:
- 先
python manage.py migrate app_name 0001回滚到冲突前版本 - 删除你本地多余的迁移文件(保留别人的)
- 重新
makemigrations生成新的
生产环境迁移策略
- 先备份数据库
- 尽量在低峰期执行(会锁定表)
- 大表大规模数据迁移建议拆成多个小批次(使用
RunPython中带batch_size或分页逻辑)
完整示例:添加字段 + 填充数据
# 1. models.py 加字段
class User(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField(null=True) # 先为空,后续填充
# 2. 生成结构迁移
# python manage.py makemigrations
# python manage.py migrate
# 3. 生成数据迁移
# python manage.py makemigrations --empty yourappname
# 4. 编辑数据迁移文件,加入:
def fill_age(apps, schema_editor):
User = apps.get_model('yourappname', 'User')
for i, user in enumerate(User.objects.iterator()):
user.age = 20 + i % 10 # 示例填充逻辑
user.save()
# 5. 执行数据迁移
# python manage.py migrate
总结一句话:结构改模型 → makemigrations → 数据想改就用 RunPython 写数据迁移 → 最后统一 migrate。