Миграция 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 не сработают.