获取模型的历史版本

时间:2017-03-02 21:35:54

标签: django django-models django-migrations

我正在使用Django 1.10,我有两个这样的模型:

class Model1:
    name = models.CharField()

class Model2:
    model1 = models.ForeignKey(Model1, default=get_default_model1)

get_default_model1函数必须获取Model1的特定实例(例如,具有特定名称),或者如果它不存在则创建它。问题是此函数导入Model1并且还将用于迁移:这意味着在Model1被修改时这种迁移可能会中断,因为它将导入新版本的Model1而不是当时需要的版本(有关此问题的更好解释,请参阅here。)

在迁移中执行RunPython操作时,您可以通过apps参数访问模型的历史版本,但事实并非如此。

我编写了以下代码来手动创建我的模型的历史版本:

from django.db import models, connection
from django.db.migrations.loader import MigrationLoader

def get_default_model1():
    loader = MigrationLoader(connection)
    apps = loader.project_state(list(loader.applied_migrations)).apps
    Model1 = apps.get_model('app', 'Model1')
    return Model1.objects.get_or_create(
        name=settings.DEFAULT_NAME,
        defaults={'name': settings.DEFAULT_NAME}
    )[0].pk

但在某些迁移中,它失败了django.db.migrations.exceptions.NodeNotFoundError: Node ('default', '0004_auto_20160423_0400') not a valid node。它似乎与替换第三方依赖的迁移有关。

有没有更好的方法来获取我的模型的历史版本或完成我在这里尝试做的事情?

1 个答案:

答案 0 :(得分:0)

您可以将get_default_model1函数定义为:

def get_default_model1(Model1):
    default_model = Model1.objects.get(...)

   return lambda: default_model


class Model1:
    name = models.CharField()


class Model2:
    model1 = models.ForeignKey(Model1, default=get_default_model1(Model1))

然后在迁移中使用它:

Model1 = apps.get_model("<your_app>", "Model1")
Model2 = apps.get_model("<your_app>", "Model2")

for model2 in Model2.objects.all():
    if not model2.model1:
        model2.model1 = get_default_model1(Model1)

我知道这看起来并不是最漂亮的,特别是你必须手动设置默认值的部分,但是你可以将正确的模型注入到函数中,这样你的目标就实现了。