我正在尝试重命名模型,并且我希望以不依赖于应用时仍然存在的旧名称的方式编写迁移。我可以以某种方式从我的迁移代码中不再具有模型的数据库表中获取数据吗?
详细说明:
我有一个Region
模型,我希望将其移入更通用的GeoObject
模型并从models.py
中移除。如果我使用GeoObjects
编写从现有Regions
创建from models import Region
的迁移代码,我必须保留Region
模型,直到我的主数据库迁移为止。但是我想编写一个迁移,以便它不依赖于Region
模型存在,只需检查数据库表是否存在并使用它。是否有可能使用Django工具,如果可能的话,不依赖于特定的数据库类型?
答案 0 :(得分:3)
是的,你可以。
但首先,你真的不应该在迁移中导入任何模型。
查看RunPython
操作,这将允许您在迁移中运行任何python代码。 RunPython
会传递给您的函数2参数:apps
和schema_editor
。第一个参数包含应用该迁移阶段的模型结构,因此如果稍后在该迁移中实际删除模型,您仍然可以使用传递给函数的apps
来访问该模型。
假设您的模型看起来像这样:
class SomeModel(models.Model):
some_field = models.CharField(max_length=32)
现在您要删除该模型,自动创建的迁移将包含:
class Migration(migrations.Migration):
dependencies = [
('yourapp', '0001_initial'), # or any other dependencies
]
operations = [
migrations.DeleteModel(
name='Main',
),
]
您可以通过在DeleteModel操作上方注入RunPython来修改该迁移:
operations = [
migrations.RunPython(
move_data_to_other_model,
move_data_back, # for backwards migration - if you won't ever want to undo this migration, just don't pass that function at all
),
migrations.DeleteModel(
name='SomeModel',
),
]
并在Migration类之前创建2个函数:
def move_data_to_other_model(apps, schema_editor):
SomeModel = apps.get_model('yourapp', 'SomeModel')
for something in SomeModel.objects.all():
# do your data migration here
o = OtherModel.objects.get(condition=True)
o.other_field = something.some_field
def move_data_back(apps, schema_editor):
SomeModel = apps.get_model('yourapp', 'SomeModel')
for something in OtherModel.objects.all():
# move back your data here
SomeModel(
some_field=something.other_field,
).save()
在models.py中不再定义模型并不重要,django可以根据迁移历史重建该模型。但请记住:在迁移中不会调用模型中的save方法(以及其他自定义方法)。此外,任何pre_save或post_save信号都不会被触发。