← Назад к вопросам
Как откатить миграции в Django?
1.3 Junior🔥 111 комментариев
#Django#Базы данных (SQL)
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Откат миграций в Django: Полный гайд
Откат миграций — это критический навык для разработки. Я много работал с миграциями, и вот всё, что нужно знать.
Основная команда: migrate
Откат всех миграций приложения
# Откатить все миграции приложения (вернуться в начальное состояние)
python manage.py migrate myapp zero
# Пример
python manage.py migrate users zero # Откатывает все миграции приложения users
Откат на конкретную миграцию
# Откатить до конкретной миграции (не включая её)
python manage.py migrate myapp 0003_previous_migration
# Пример
python manage.py migrate users 0005_add_profile
# Вернётся к состоянию после миграции 0005_add_profile
Откат на N шагов назад
# К сожалению, Django не имеет встроенной команды для откатов на N шагов
# Нужно найти конкретную миграцию, но есть хитрость:
# Просмотр всех миграций
python manage.py showmigrations myapp
# Вывод примерно такой:
# users
# [ ] 0001_initial
# [X] 0002_add_email
# [X] 0003_add_profile
# [X] 0004_rename_field
# [X] 0005_add_avatar
# Если текущее состояние — 0005, и мы хотим откатить на 2 шага (вернуться к 0003)
python manage.py migrate users 0003_add_profile
Примеры для разных ситуаций
Ситуация 1: Откатить последнюю миграцию
# Сначала смотрим, какие миграции применены
python manage.py showmigrations
# Находим, какая миграция была до текущей
# Если текущая 0005_add_avatar, и до неё была 0004_rename_field, то:
python manage.py migrate myapp 0004_rename_field
Ситуация 2: Полный откат всех миграций в БД
# ОСТОРОЖНО: Это удалит ВСЕ изменения БД!
python manage.py migrate myapp zero
# Для всех приложений
python manage.py migrate zero # Откатывает все миграции всех приложений
Ситуация 3: Откатить миграции нескольких приложений
# Откатить приложение users до нуля
python manage.py migrate users zero
# Откатить приложение posts до миграции 0003
python manage.py migrate posts 0003_add_comments
# Откатить приложение core до нуля
python manage.py migrate core zero
Практический пример: Desenvolvimento workflow
# 1. Видим, что последняя миграция вызвала проблему
python manage.py showmigrations
# Output:
# users
# [X] 0001_initial
# [X] 0002_add_email
# [X] 0003_add_profile <- Эта вызывает ошибку
# 2. Откатываем последнюю миграцию
python manage.py migrate users 0002_add_email
# 3. Удаляем файл неправильной миграции
rm myapp/migrations/0003_add_profile.py
# 4. Создаём исправленную версию
python manage.py makemigrations users
# 5. Применяем заново
python manage.py migrate users
Состояние БД во время миграций
# migrations/0003_add_field.py
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('myapp', '0002_previous_migration'),
]
operations = [
migrations.AddField(
model_name='user',
name='phone',
field=models.CharField(max_length=20, default=''),
preserve_default=False,
),
]
Откат этой миграции: Удалит поле phone из таблицы user
Просмотр статуса миграций
# Все миграции во всех приложениях
python manage.py showmigrations
# Все миграции конкретного приложения
python manage.py showmigrations myapp
# С подробностью
python manage.py showmigrations --verbosity 2
# Только примененные
python manage.py showmigrations --list | grep '\[X\]'
# Только не примененные
python manage.py showmigrations --list | grep '\[ \]'
Проверка SQL, который будет выполнен
# Посмотреть SQL без применения
python manage.py sqlmigrate myapp 0003_add_profile
# Для отката (требует некоторой подготовки)
python manage.py sqlmigrate myapp 0003_add_profile --backwards # Django < 3.1
Обработка проблем при откате
Проблема 1: "django.db.utils.IntegrityError: duplicate key value"
# migrations/0005_fix_migration.py
from django.db import migrations, models
def clean_duplicates(apps, schema_editor):
"""Удаляет дубликаты перед откатом"""
User = apps.get_model('users', 'User')
# Логика удаления дубликатов
User.objects.filter(email='').delete()
class Migration(migrations.Migration):
dependencies = [
('users', '0004_previous'),
]
operations = [
migrations.RunPython(clean_duplicates, migrations.RunPython.noop),
]
Проблема 2: Окружение развивается, откат не работает
# ОПАСНО: Принудительный откат (может привести к несогласованности)
python manage.py migrate --fake myapp zero
# Это только обновит таблицу django_migrations, не изменяя БД
# Используй только если знаешь, что делаешь!
Скрипт для удобного откатывания
#!/bin/bash
# reset_migrations.sh
if [ -z "$1" ]; then
echo "Usage: ./reset_migrations.sh <app_name> [target_migration]"
exit 1
fi
APP=$1
TARGET=${2:-"zero"}
echo "Rolling back migrations for app: $APP to: $TARGET"
python manage.py migrate $APP $TARGET
echo "Done!"
Проверка перед откатом
# 1. Убедитесь в резервной копии БД
pg_dump mydatabase > backup_$(date +%Y%m%d_%H%M%S).sql # PostgreSQL
mysqldump mydatabase > backup_$(date +%Y%m%d_%H%M%S).sql # MySQL
# 2. Проверьте зависимости миграций
python manage.py showmigrations
# 3. Проверьте, есть ли данные, которые будут потеряны
python manage.py dbshell
# SELECT COUNT(*) FROM users_phone; -- Если откатываем удаление поля
# 4. Только потом откатывайте
python manage.py migrate myapp <target_migration>
Production: Безопасный откат
# На production НИКОГДА не откатывайте без подготовки!
# 1. Заблокировать приложение для новых операций
# (Используй maintenance mode)
# 2. Создать резервную копию
sudo pg_dump production_db > prod_backup_2026_03_22.sql
# 3. Откатить в отдельной ветке БД для тестирования
python manage.py migrate myapp 0002_previous_migration --database=test_backup
# 4. Если всё ок, откатить в боевой БД
python manage.py migrate myapp 0002_previous_migration
# 5. Снять блокировку
Итоговый чеклист откатывания
- Создал резервную копию БД
- Посмотрел
showmigrationsи знаю текущее состояние - Идентифицировал целевую миграцию для отката
- На development — проверил откат локально
- Выполнил команду:
python manage.py migrate myapp <target> - Проверил, что БД теперь в правильном состоянии
- Если нужно, удалил файлы миграций с диска
- Создал новые миграции если потребовалось
- Применил новые миграции:
python manage.py migrate
Типичные ошибки
# ОШИБКА 1: Неправильное имя миграции
python manage.py migrate users 0002_add_email_field # Опечатка в имени
# ОШИБКА 2: Забыли приложение
python manage.py migrate 0002_add_email # Какое приложение?
# ОШИБКА 3: Применили откат, но модель не обновилась
# migrations откатились, но код всё ещё ссылается на удаленное поле
# Решение: Обновить код модели вручную
# ОШИБКА 4: Не учли зависимости
# Миграция 0005 зависит от 0004
# Если откатить 0004, 0005 останется висеть
python manage.py migrate myapp zero # Откатить всё сразу
Итоговая рекомендация
В Development: Откатывай свободно, это помогает работать итеративно В Production: Никогда не откатывай — создавай новые миграции для исправления ошибок
Лучший подход: пишешь миграцию → видишь проблему → откатываешь → удаляешь файл → пишешь правильную миграцию → применяешь заново.