我接手了一个混乱的项目,所以我一直在清理和删除大量的模型。有时候,我必须在删除之前将数据从模型复制到另一个模型中。我一直在编写可以同时完成这两项工作的迁移。有时候一切都很正常。但有时候它 * 不 * 工作。
流程:
- 对代码库进行必要的更改,包括删除模型及其引用。
- 创建具有以下特点的迁移:
- 从模型中复制数据
- 删除模型
以下是此类迁移的示例:
from django.db import migrations, models
def doit(apps, schema_editor):
OldModel = apps.get_model("myapp", "OldModel")
NewModel = apps.get_model("myapp", "NewModel")
for obj in OldModel.objects.all():
...transform and save data in NewModel...
class Migration(migrations.Migration):
dependencies = [("myapp", "0001_initial")]
operations = [
migrations.RunPython(doit, reverse_code=migrations.RunPython.noop),
migrations.DeleteModel(name="OldModel"),
]
有时迁移会按预期运行。有时迁移会失败,并出现以下情况:
第一个月
我找不到有效的迁移和以这种方式失败的迁移之间有什么显著的区别,我已经有了很多这样的例子,并且绞尽脑汁试图找出区别。
我的理解是,通过RunPython()
方法传递给函数的apps
对象提供了所有模型的模拟 *,因为它们在迁移链中的那个点上存在 *,而不管代码库的状态如何,所以模型不再存在也没有关系。
然而,有时候确实如此。
1条答案
按热度按时间u3r8eeie1#
刚刚有了一个小小的突破。下面是我当前上下文迁移的一个片段:
在迁移过程中,我得到了
FundManager
的一个LookupError--尽管它实际上在两行以上就可以找到。通过检查痕迹簿,我们发现了几条线索:
dirtyfields
包正在被调用,这提醒我们“模拟模型”只是表面的-下面的真实的基类仍然被引用dirtyfields
的执行线程将导致另一个对apps.get_model()
的调用,用于“FundManager”,但这一次它是真实的的django.apps
,而不是迁移本身中使用的模拟django.apps
所以我认为这就是原因。我不知道正确的解决办法是什么。我想到的是:
1.避免使用像
dirtyfields
包这样很酷的基类(不是一个好的选择,因为它非常有用)1.使用
RunSQL
代替RunPython
进行数据迁移(与Python解决方案相比通常非常困难)**更新:**刚刚想到第三个选项-编辑我的“0001_initial.py”迁移并从FundManager的
CreateModel
语句中删除dirtyfields
基类:我 * 仍然 * 完全不知道为什么这对 * 这个 * 模型是必要的,而不是我在 * 相同 * 迁移中删除的另一个几乎相同的模型,它在没有
LookupError
的情况下是可删除的,* 尽管 * 仍然附加了它的dirtyfields
基类...