Миграция Django 1.8: есть ли способ получить данные из таблицы базы данных, у которой больше нет модели?

Я пытаюсь переименовать модель, и я хотел бы написать миграцию так, чтобы она не зависела от старого имени, которое все еще присутствует во время его применения. Могу ли я как-то получить данные из таблицы базы данных, в которой больше нет модели в моем коде миграции?

Подробности: у меня есть Region модель, которую я хочу перейти в более общий GeoObject модель и удалить из models.py, Если я напишу свой код миграции, который создает GeoObjects из существующих Regions с from models import Region Я должен буду держать Region модель, пока моя основная база данных не будет мигрировать. Но я бы хотел написать миграцию, чтобы она не зависела от Region присутствующая модель, просто проверьте, что таблица базы данных существует, и используйте ее. Можно ли сделать это с помощью инструментов Django, не завися от конкретного типа базы данных, если это возможно?

1 ответ

Решение

Да, ты можешь.

Но, во-первых, вам не следует импортировать какую-либо модель внутри миграции.

Взгляни на 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',
        ),
    ]

Вы можете изменить эту миграцию, введя RunPython чуть выше операции DeleteModel:

    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',
        ),
    ]

и создание 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 может перестроить эту модель на основе истории миграции. Но помните: метод сохранения из ваших моделей (и других пользовательских методов) не будет вызываться при переносе. Также любые сигналы pre_save или post_save не сработают.

Другие вопросы по тегам