Django4.0 迁移-数据迁移
除了改变数据库架构外,你还可以使用迁移来改变数据库本身的数据,如果你想的话,还可以结合架构来改变。
更改数据的迁移通常称为“数据迁移”;最好将它们写成单独的迁移,与架构迁移放在一起。
Django 无法像架构迁移那样自动为您生成数据迁移,但是编写它们并不难。Django 中的迁移文件是由 Operations
组成的,你用于数据迁移的主要操作是 RunPython
。
首先,制作一个可以使用的空迁移文件(Django 会将文件放在正确的位置,提供一个名称,并为你添加依赖项):
python manage.py makemigrations --empty yourappname
然后,打开文件;它应该是这样的:
# Generated by Django A.B on YYYY-MM-DD HH:MM
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('yourappname', '0001_initial'),
]
operations = [
]
现在,你需要做的就是创建一个新的函数,让 RunPython
使用它。RunPython
需要一个可调用对象作为它的参数,这个可调用对象需要两个参数——第一个是 应用注册表 ,其中加载了所有模型的历史版本,以匹配迁移所在的位置,第二个是 SchemaEditor
,你可以用它来手动实现数据库架构的变更(但要注意,这样做会混淆迁移自动检测器!)
让我们编写一个迁移,使用 first_name 和 last_name 的组合值填充新的 name 字段(我们已经意识到,并不是每个人都有名字和姓氏)。 我们需要做的就是使用历史模型并对行进行迭代:
from django.db import migrations
def combine_names(apps, schema_editor):
# We can't import the Person model directly as it may be a newer
# version than this migration expects. We use the historical version.
Person = apps.get_model('yourappname', 'Person')
for person in Person.objects.all():
person.name = '%s %s' % (person.first_name, person.last_name)
person.save()
class Migration(migrations.Migration):
dependencies = [
('yourappname', '0001_initial'),
]
operations = [
migrations.RunPython(combine_names),
]
完成后,我们可以像往常一样运行 python manage.py migrate
,数据迁移将与其他迁移一起运行。
您可以将第二个可调用对象传递给 RunPython
以运行撤销迁移时要执行的任何逻辑。 如果忽略此可调用对象,则撤销迁移将引发异常。
从其他应用访问模型
在编写使用来自迁移所在应用以外的其他应用模型的 RunPython
函数时,迁移的 dependencies
属性应包括所涉及的每个应用程序的最新迁移,否则当你尝试使用 apps.get_model()
在 RunPython
函数中获取模型时,你可能会得到 LookupError: No installed app with label 'myappname'
。
在下面的例子中,我们在 app1 中进行迁移,需要使用 app2 中的模型。我们不关心 move_m1 的细节,只关心它需要访问两个应用程序的模型。因此,我们添加了一个依赖关系,指定 app2 最后一次迁移:
class Migration(migrations.Migration):
dependencies = [
('app1', '0001_initial'),
# added dependency to enable using models from app2 in move_m1
('app2', '0004_foobar'),
]
operations = [
migrations.RunPython(move_m1),
]