Ответ
Для выполнения произвольного Python-кода в Django-миграциях используется операция migrations.RunPython
. Это необходимо для сложных операций с данными, которые нельзя выразить через стандартные изменения схемы, например, для миграции данных между полями, создания начальных объектов или выполнения кастомной логики.
RunPython
принимает два аргумента:
forward_func
: Функция, которая будет выполнена при применении миграции.reverse_func
: Функция, которая будет выполнена при отмене миграции (опционально, но рекомендуется).
Обе функции получают аргументы apps
(исторический реестр приложений) и schema_editor
.
Пример:
from django.db import migrations
def create_initial_data(apps, schema_editor):
# Получаем модель из исторической версии приложения 'myapp'
MyModel = apps.get_model('myapp', 'MyModel')
# Создаем объекты
MyModel.objects.create(name='Test Item 1', value=10)
MyModel.objects.create(name='Test Item 2', value=20)
def reverse_create_initial_data(apps, schema_editor):
# Удаляем созданные объекты при откате миграции
MyModel = apps.get_model('myapp', 'MyModel')
MyModel.objects.filter(name__startswith='Test Item').delete()
class Migration(migrations.Migration):
dependencies = [
# Укажите зависимости от предыдущих миграций
('myapp', '0001_initial'),
]
operations = [
migrations.RunPython(
create_initial_data,
reverse_create_initial_data
),
]
Важно: Всегда используйте apps.get_model('app_label', 'ModelName')
вместо прямого импорта моделей (from myapp.models import MyModel
). Это гарантирует, что вы работаете с исторической версией модели, которая существовала на момент создания данной миграции, а не с текущей версией, что предотвращает ошибки при изменении схемы в будущем.