Миграции в django: makemigrations, migrate и схема БД
Создание миграций, применение, откат, конфликты, типичные ошибки и их решения, шпаргалка и цикл работы с изменениями базы данных в Django.


В процессе разработки сайта или иного приложения на Django, структура базы данных может меняться.
Важно, чтобы все изменения корректно синхронизировались между базой данных и кодом django моделей, чтобы это гарантировать давайте посмотрим что такое django миграции.
Миграции это механизм позволяющий отслеживать изменения моделей приложений django и актуализировать структуру соответствующих таблиц базы данных.
С помощью миграций можно:
создавать таблицы
добавлять и изменять столбцы
задавать ограничения (например уникальность ячеек)
хранить историю изменений
Папка миграций (migrations) содержит__init__.py следовательно является питон пакетом (package), каждый файл миграции это модуль (module) на языке питон, в таких файлах описаны изменения произведенные с момента последней миграции.
blog/
├── migrations/
│ ├── __init__.py
│ ├── 0001_initial.py
│ └── 0002_article_published.py
├── models.py
└── apps.pyпример папки миграций в django
Важно понимать что миграции не работают в автоматическом режиме, а порой требуют только ручного вмешательства и холодного ума.
Следует различать три отдельных сущности, живущих каждая по своим законам.
django модель - содержит актуальную информацию о таблице для кодовой базы django
migrationпапка каждого из приложений django содержит последний слепок измененийбаза данных содержит последние примененные к ней изменения
Разделив для себя три сущности описанные выше, можем описать цикл миграции из трех шагов:
создание или изменение кода модели
автоматизированное создание в папке
migrationsпромежуточных файлов с выявленными изменениями моделиприменение изменений на подключенную в настройках базу данных
Для корректной работы Django приложения, все три сущности яния должны быть синхронизированы - отображать одинаковую информацию по своей сути.
Команда makemigrations анализирует изменения в моделях и создаёт новые файлы миграций.
Обычно её запускают после добавления модели, изменения поля или настройки ограничений.
python manage.py makemigrations blogпример запуска makemigrations в Django для конкретного приложения blog
Для просмотра операций, которые будут записаны можно использовать подробный вывод, добавив флаг --verbosity 3.
Допустим, в модели статьи добавили поле is_published:
class Article(models.Model):
title = models.CharField(max_length=200)
body = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
is_published = models.BooleanField(default=False)пример добавления поля в модель django
Чтобы сделать промежуточный файл, который запишет изменения, запустим команду
python manage.py makemigrations blogпример запуска команды makemigrations в django
Если все прошло успешно в папке приложения blog в папке migrations появится новый файл типа: 0002_article_is_published.py, внутри будет описана операция AddField.
Конкретное имя файла зависит от изменений и состояния истории миграций.
makemigrations не применяет изменения к базе данных.
Команда лишь создаёт промежуточные файлы миграций.
Если в таблице уже есть строки - записи, добавление поля без null=True и без default может потребовать значения по умолчанию.
Например добавим новое поле «имя автора» (author_name) и представим что в таблице уже были статьи.
author_name = models.CharField(max_length=100)пример создания нового поля в Django models
Выполнив команду makemigrations команда предложит указать разовое значение для миграции либо завершится ошибкой, если подходящее значение не будет определено.
It is impossible to add a non-nullable field 'author_name' to article without specifying a default. This is because the database needs something to populate existing rows.
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit and manually define a default value in models.py.
Select an option:
пример django makemigrations просит установить значение
Не следует рисковать добавляя значение по умолчанию или фиктивное значение.
Решение в поэтапной миграции: сначала добавить разрешение на отсутствие поля blank=True у существующих записей, далее заполнить данные, а затем сделать поле обязательным.
Команда migrate отвечает за применение промежуточных файлов из папки migrations каждого подключенного приложения к базе данных.
python manage.py migrateпример вызова команды migrate в Django
Django определяет миграции, которые ещё не применены, и выполняет их в порядке зависимостей.
Чтобы применить определённую миграцию приложения можно использовать команду:
python manage.py migrate blog 0002пример применения определенной миграций django приложения blog
На боевой машине важно убедиться в наличии резервной копии базы, чтобы при необходимости все вернуть, а так же посмотреть план изменений.
python manage.py migrate --plan команда позволяет узнать план изменений
Команда showmigrations показывает миграции и отмечает применённые:
python manage.py showmigrationsпример использования showmigrations в Django
Обычно [X] означает, что миграция отмечена как применённая в выбранной базе данных, а [ ] — что она не применена.
Чтобы посмотреть миграции в более подробном виде, можно использовать команду:
python manage.py showmigrations --planпример команды более подробных миграций в django
Чтобы посмотреть SQL, который Django сгенерирует для конкретной миграции, требуется выполнить команду:
python manage.py sqlmigrate blog 0002пример команды для просмотра SQL в django migrations
Команда помогает разобраться в изменениях таблиц и ограничениях.
Написание SQL меняется в зависимости от используемой СУБД, поэтому вывод для PostgreSQL, MySQL и SQLite может различаться.
В некоторых случаях миграции могут зависеть друг от друга.
Например, миграция приложения blog может ссылаться на модель пользователя из приложения accounts .
Зависимости указываются в атрибуте dependencies:
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("blog", "0001_initial"),
]
operations = [
migrations.AddField(
model_name="article",
name="is_published",
field=models.BooleanField(default=False),
),
]пример зависимостей в Django migration файле
Чтобы определить порядок миграций Django строит граф зависимостей и выбирает последовательность, в которой операции можно выполнить безопасно.
Стоит проявить внимательность при желании удалить файлы миграций или код в моделях, так как другие миграции могут ссылаться на них, а их отсутствие может привести к поломке системы.
Чтобы откатить миграции приложения на несколько шагов назад, требуется указать предыдущую миграцию.
Это уничтожит столбцы в базе данных, которые были указаны в отмененных файлах миграций.
Перед откатом проверьте план и сделайте резервную копию базы данных.
python manage.py migrate blog 0001пример команды отката миграции
Например если актуальная миграция в базе данных была 0002, эта команда удалит действия миграции 0002, приведя столбцы к состоянию после миграции 0001.
Чтобы отменить все миграции конкретного приложения:
python manage.py migrate blog zeroпример команды удаления всех действий миграций конкретного приложения
Чтобы вернуться к последней миграции, снова выполните:
python manage.py migrateкоманда применения миграции в Django
Это снова применит все существующией файлы в папке migrations каждого подключенного приложения, но не вернет данные столбцов.
Ниже рассмотрим распространенные ошибки при работе с миграциями в django и их решения.
Требуется проверить окно базы данных, когда оно последний раз обновлялось.
Если окно таблицы в базе данных обновлено, но поле так и не появилось можно попробовать ввести команду:
python manage.py showmigrations
python manage.py migrate --planкоманда проверки файлов миграций и плана действий
Если файл миграций не указан требуется команда: python manage.py makemigrations, при наличии файла, команда: python manage.py migrate
Django не обнаружил изменений моделей, требующих новой миграции. Проверьте, что:
приложение добавлено в INSTALLED_APPS
изменённая модель наследуется от models.Model
изменения действительно влияют на состояние модели, отслеживаемое миграциями
вы запускаете команду в правильном проекте и окружении
Не каждое изменение Python-кода требует миграции: например, изменение метода модели без изменения её схемы обычно не создаёт миграцию.
Эта ошибка означает, что история применения миграций не согласуется с зависимостями: например, миграция отмечена применённой раньше, чем её зависимость.
Не удаляйте строки из migrations и не применяйте--fake наугад.
Сначала выясните, какая база используется, какие миграции реально применены и как возникло расхождение.
Затем составьте план восстановления истории и схемы для конкретного окружения.
База данных уже содержит объект, который миграция пытается создать. Возможные причины:
схема изменялась вручную
миграции были применены к базе другим способом
история миграций не соответствует фактической схеме
база была скопирована или восстановлена частично
Сравните SQL миграции с реальной схемой и историей миграций.
Не удаляйте таблицу или столбец, пока не убедитесь, что данные можно восстановить.
Если существующие строки не могут получить значение нового обязательного поля, миграция может потребовать значение по умолчанию или завершиться ошибкой.
Для крупных таблиц часто безопаснее разделить изменение на этапы:
добавить поле, допускающее отсутствие значения (
blank=True)сделать код, который заполняет поле для новых записей
заполнить старые записи отдельной миграцией данных или командами django (commands)
убедиться, что пустых значений больше нет
сделать поле обязательным отдельной миграцией
Такой подход позволяет контролировать преобразование данных и уменьшает риск мучительных последствий.
Флаг --fake отмечает миграцию как применённую или отменённую в истории Django, не выполняя соответствующие SQL-операции:
python manage.py migrate blog 0002 --fakeпример пустых миграций командой --fake
Флаг --fake может понадобиться при восстановлении согласованности истории, если схема уже приведена к нужному состоянию другим способом.
При использовании--fake Django не проверяет, что фактическая схема действительно соответствует миграции.
Использование флага без понимания последствий может создать дополнительные серьезные проблемы в базе.
Флаг--fake-initial помогает Django распознать ситуацию, когда начальная миграция приложения соответствует уже существующим таблицам.
Он полезен, например, при подключении Django к базе с ранее созданными таблицами.
Правильные действия помогают избежать проблем при совместной разработке и развёртывании.
Храните миграции в системе контроля версий.
Файлы миграций - часть исходного кода проекта.
Проверяйте план перед применением.
Используйте
python manage.py migrate --plan.Проверяйте SQL при сложных изменениях.
Команда
sqlmigrateпомогает увидеть операции, специфичные для используемой СУБД.Предварительно тестируйте миграции на копии или тестовой базе.
Особенно если они меняют или удаляют данные.
Делайте резервные копии.
В случае разрушительных изменений данных базы, требуется возможность восстановления.
Не редактируйте старые миграции без необходимости.
Изменение существующих миграций может сломать систему работы ORM и повредить данные.
Учитывайте совместимость версий приложения.
Проверяйте старый и новый код на одной копии или тестовой базе для избежания рискованных ситуаций.
Не запускайте миграции параллельно из нескольких процессов без продуманной процедуры развёртывания
Назначьте единый шаг развертывания (deploy), который отвечает за миграции.
| Команда | Назначение |
|---|---|
python manage.py makemigrations | Создать миграции на основе изменений моделей |
python manage.py makemigrations blog | Создать миграции для приложения blog |
python manage.py migrate | Применить все ожидающие миграции |
python manage.py migrate blog | Применить миграции приложения blog |
python manage.py migrate blog 0001 | Перейти к состоянию после миграции 0001 |
python manage.py migrate blog zero | Отменить все миграции приложения blog |
python manage.py showmigrations | Посмотреть состояние миграций |
python manage.py migrate --plan | Посмотреть план применения |
python manage.py sqlmigrate blog 0002 | Посмотреть SQL конкретной миграции |
При обычном изменении модели придерживайтесь последовательности:
# Создать миграцию
python manage.py makemigrations
# Проверить созданные файлы и зависимости
python manage.py showmigrations
# Посмотреть план
python manage.py migrate --plan
# При необходимости проверить SQL
python manage.py sqlmigrate blog 0002
# Применить миграции
python manage.py migrateпример последовательностей работы с миграциями в Django
После создания файла миграции просмотрите его содержимое: автоматическая генерация экономит время, но не заменяет проверку.
Убедитесь, что операции корректны, значения по умолчанию соответствуют изначальным ожиданиям, а преобразования данных безопасны.
Если у вас остались вопросы по Django миграциям при работе с базой данных, вы можете обратиться за консультацией к программисту.





