2.0Kпросмотров
90.5%от подписчиков
23 февраля 2026 г.
Score: 2.2K
Опасность использования loaddata в миграциях Есть одна команда в Django, которая работает идеально - ровно до того момента, пока ты не попробуешь накатить миграции с нуля Речь о call_command("loaddata", ...) внутри миграции Выглядит невинно: добавляешь начальные данные в базу прямо при создании схемы - удобно, лаконично. Но потом ты добавляешь новое поле в модель, и при прогоне миграций с нуля всё ломается Почему? Когда ты пишешь RunPython и вызываешь apps.get_model() - ты получаешь историческую модель. Это не та модель, что у тебя сейчас в models.py, а её слепок на момент конкретной миграции. Django специально реконструирует её из цепочки миграций, чтобы INSERT и UPDATE содержали только те колонки, которые реально существуют в базе прямо сейчас - в процессе накатки А вот loaddata на эту логику плевать хотел - он всегда импортирует модель напрямую из приложения, то есть берёт текущее состояние models.py со всеми полями, которые ты добавил позже. В итоге команда пытается сделать INSERT с колонкой, которой в базе ещё нет Решение - отказаться от loaddata в пользу RunPython Читаем JSON сами, создаём объекты через историческую модель из apps.get_model(). Тогда Django собирает INSERT только по полям, которые реально существуют на момент этой миграции - и никакие будущие изменения схемы её не сломают def load_fixture(apps, schema_editor): MyModel = apps.get_model("myapp", "MyModel") MyModel.objects.all().delete() fixture_path = ( Path(file).resolve().parent.parent / "fixtures" / "my_fixture.json" ) with fixture_path.open("r", encoding="utf-8") as f: data = json.load(f) objs = [ MyModel(**item["fields"], pk=item.get("pk")) for item in data if item.get("model") == "myapp.mymodel" ] MyModel.objects.bulk_create(objs) Простое правило - миграции должны быть детерминированными и самодостаточными, без привязки к текущему состоянию моделей Поддержать на Boosty
Посмотреть на Youtube