Get the historical version of the model

I work with Django 1.10 and I have two such models:

class Model1:
    name = models.CharField()

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

The function get_default_model1must obtain a specific instance Model1(for example, with a specific name) or create it if it does not exist. The problem is that this function imports Model1and will also be used during migration: this means that such migration is likely to be broken when it is changed Model1, as it imports a new version Model1instead of the required version at that time (see here for a better explanation this problem).

When you perform an operation RunPythonduring the migration process, you have access to historical versions of the model with an argument apps, but this is not the case.

I wrote the following code to manually create a historical version of my model:

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

But in some migrations he fails with django.db.migrations.exceptions.NodeNotFoundError: Node ('default', '0004_auto_20160423_0400') not a valid node. This seems to be related to replacing third-party dependency migration.

Is there a better way to get a historical version of my model or do what I'm trying to do here?

+4
source share
1 answer

You can define a get_default_model1function as:

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))

And then use it in hyphenation:

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)

I know that this does not look the most beautiful, especially where you need to manually set the default value, but you get the right model introduced into the function, so your goal is achieved.

0
source

Source: https://habr.com/ru/post/1671303/


All Articles