Что такое миграции в django

Документация Django 1.7

Django использует миграции для переноса изменений в моделях (добавление поля, удаление модели и т.д.) на структуру базы данных. Миграции создавались в основном для автоматической работы, но вам необходимо знать когда их создавать, запускать и как решать различные проблемы.

Краткая история¶

До версии 1.7, Django позволял только добавлять новые модели в базу данных; не было возможности изменять или удалять существующие модели, используя команду syncdb (предок команды migrate ).

Сторонние инструменты, самый известный South, позволяли создавать и выполнять миграции. Со временем было решено перенести этот функционал в Django.

Две команды¶

Django предоставляет две команды для работы с миграциями и структурой базы данных:

Файлы с миграциями находятся в каталоге “migrations” приложения. Они являются частью приложения и должны распространятся вместе с остальным кодом приложения. Они должны создаваться при разработке и потом применятся на машинах коллег, тестовом и “боевом” серверах.

Миграции работают идентично на одном и том же наборе данных. Это означает, что на сервере разработке, тестовом и “боевом” серверах вы получите один и тот же результат при одинаковых условиях выполнения миграций.

Поддержка бэкендами¶

Миграции поддерживаются всеми бэкендами, которые предоставляет Django, как и сторонними, если они реализуют API внесения изменений в структуру базы данных (через класс SchemaEditor).

Тем не менее, некоторые базы данных поддерживают больше возможностей, чем другие, в случаях когда речь идёт о миграциях схемы. Некоторые ограничения будут описаны далее.

PostgreSQL¶

PostgreSQL предоставляет больше всего возможностей для миграций структуры данных. Единственное ограничение в том, что добавление столбцов со значениями по умолчанию вызывает полную перезапись таблицы и требует времени, пропорциональное её размеру.

MySQL¶

В MySQL отсутствует поддержка транзакций при изменении структуры. Это означает, что если миграция не выполнится из-за ошибки вам придется вручную откатывать изменения, чтобы попытаться снова (т.к. невозможно вернуться к исходному состоянию автоматически).

Кроме того, MySQL будет полностью переписать таблицы почти для каждой операции изменения структуры, это занимает время, пропорциональное количеству строк в таблице. На медленном оборудовании это может занимать больше, чем минута на миллион строк. Добавление нескольких столбцов в таблицу с всего несколькими миллионами строк может заблокировать ваш сайт на более чем десять минут.

Наконец, MySQL имеет достаточно малый предел для длины имен столбцов, таблиц и индексов, а также ограничение на общий размер всех столбцов и индексов. Это означает, что индексы, которые могут создать другие бэкенды, не будут созданы MySQL.

SQLite¶

SQLite очень плохо поддерживает изменения в структуре базы данных, но Django пытается эмулировать их следующим образом:

Создание новой таблицы для новой структуры

Копирование данных в новую таблицу

Удаление старой таблицы

Переименование новой таблицы

Этот процесс как правило хорошо работает, но может быть медленным и иногда глючит. Не рекомендуется использовать и мигрировать SQLite на “боевом” сервере, если вы не очень осведомлены о рисках и его ограничениях. Django поддерживает SQLite, чтобы позволить разработчикам использовать SQLite для разработки простых проектов.

Работа с миграциями¶

Создав новые миграции, вам следует применить их к вашей базе данных, чтобы убедиться, что всё работает:

Команда работает в два этапа. Сначала она синхронизирует приложения без миграций (по сути выполняет действия аналогичные syncdb ), а затем применяются миграции, которые ещё не применялись к базе данных.

Контроль версий¶

Поскольку миграции хранятся в системе контроля версий, вы будете иногда сталкиваться с ситуациями, когда вы и другой разработчик одновременно добавили миграции для одного приложения, в результате чего появилось две миграции с одним и тем же номером.

Зависимости¶

Такое поведение зависимостей влияет на большинство миграционных операций, которые вы ограничили рамками одного приложения. Подобное ограничение (в makemigrations или migrate ) было отличным обещанием, но не гарантией. Любое другое приложение, которое потребуется для удовлетворения зависимости, будет использовано автоматически.

Обратите внимание, приложения без миграций не могут зависеть от приложений с миграциями. Это означает, что приложение без миграций не могут содержать ForeignKey или ManyToManyField на приложение с миграциями, в некоторых случаях это будет работать, но скорее всего вы получите ошибку.

Файлы с миграциями¶

Миграции сохраняются в так называемых “файлах миграции”. Это обычные Python файлы с классом миграции, который соблюдает определенный интерфейс. В нём декларативно можно описать все необходимые операции и прочее.

Базовый файл миграции выглядит следующим образом:

Скорее всего вам никогда не понадобится менять сгенерированные миграции, но при необходимости вы можете сами написать миграцию. Некоторые сложные изменения Django не может автоматически определить, в таких случаях их необходимо описать самостоятельно. Но не бойтесь, это несложно.

Собственные поля¶

Добавление миграций в приложение¶

Если ваше приложение уже содержит модели и таблицы в базе данных, но не содержит миграции (например, вы используете приложение для предыдущих версий Django), вам необходимо преобразовать, чтобы использовать миграции. Это просто:

Обратите внимание, это работает только при соблюдении следующих условий:

Вы не меняли модели после создания таблиц в базе данных. Чтобы миграции сработали, необходимо сначала создать начальную миграцию, а потом вносить изменения, т.к. Django определяет изменения по файлам миграций, а не структуре в базе данных.

Вы не меняли самостоятельно структуру базы данных. Django не сможет определить, что структура базы данных не соответствует структуре ваших моделей. Скорее всего вы получите ошибку при выполнении миграций.

“Исторические” модели¶

Т.к. невозможно сериализовать произвольный код Python, эти версии моделей не будут содержать методы или менеджеры, который вы добавили в модели. Однако, модели будут содержать аналогичные поля, связи и параметры Meta (с учетом версии модели, так что они могут отличаться от моделей, которые находятся на данный момент в приложении).

Ссылки на функции, которые используются в параметрах поля (например, upload_to и limit_choices_to ), будут сохранены в миграциях. Такие функции нельзя удалять из кода проекта, пока миграции ссылаются на них.

В дополнение, родительские классы модели также сохраняются в миграциях в виде указателей. Их необходимо сохранять, пока существует миграция, которая ссылается на них. Но в качестве бонуса у вас будет доступ ко всем методам и менеджерам из родительских классов. Так что, если вам действительно необходим доступ в миграциях к собственным методам и менеджерам, вы можете вынести их в родительский класс.

Миграция данных¶

Вы можете использовать миграции не только для изменения структуры базы данных, но и для изменения данных. Можно и в контексте изменения структуры, чтобы мигрировать данные на новую структуру таблицы.

Миграции, которые изменяют данные, обычно называют “миграциями данных”. Их лучше выносить в отдельную миграцию.

Для начала создайте пустую миграцию (Django создаст файл миграции, положит его в правильно место, создаст название и добавит необходимые зависимости):

Теперь откройте файл, он будет выглядеть следующим образом:

Теперь выполним python manage.py migrate и миграция данных будет применена вместе с остальными миграциями.

Если вы хотите узнать как писать более сложные миграции, или как создавать миграции с нуля, смотрите раздел об операциях в миграциях.

Объединение миграций¶

Вы можете создавать сколько угодно миграций и не задумываться об их количестве. Код миграций оптимизирован и может работать с сотнями миграций за вменяемое время. Но, если вы хотите уменьшить количество миграций, вы можете объединить их.

Объединение позволяет сократить количество миграций до одной (или нескольких), которая будет выполнять аналогичные изменения структуры.

Новые файлы миграций содержат пометку, что они созданы на основе существующих миграций, таким образом они могут существовать и использоваться параллельно со старыми миграциями. Django самостоятельно переключится между этими миграциями, учитывая в какой точке истории миграций вы сейчас находитесь. Если вы применили только часть миграций, которые были объединены, Django будет использовать старые миграции, пока не выполнит их, затем переключится на новую историю. Для новой базы данных сразу будут использоваться новые миграции, старые миграции будут пропущены.

Это позволяет объединить миграции и не сломать проект на сервере, который ещё не обновили до последней версии. Рекомендуем следующую последовательность действий: объединяем миграции, старые не удаляем, коммитим и обновляем все сервера при следующем релизе (если это распространяемое приложение, убеждаемся, что все пользователи обновились до последней версии), удаляем старые миграции, коммитим и обновляем сервера до последней релизной версии.

После объединения миграций закоммитьте их, не удаляя старые миграции. После этого обновите все установленные версии проекта.

После этого объединенную миграцию можно преобразовать в обычную начальную миграцию:

Удалите все миграции, которые она заменяет

Удалите аргумент replaces в классе Migration объединенной миграции (он указывает Django, что это объединенная миграция)

Объединив миграции в новую, вы не можете снова использовать её при новом объединении, пока она не будет преобразована в обычную миграцию.

Сериализация значений¶

Django позволяет сериализовать следующее:

Ссылку на любую функцию или метод (например datetime.datetime.today )

Любой объект с методом deconstruct() (смотрите ниже)

Django может сериализовать следующее только в Python 3:

Непривязанные методы в теле класса (смотрите ниже)

Django не может сериализовать:

Экземпляры произвольного класса (например MyClass(4.3, 5.7) )

Т.к. __qualname__ был добавлен только в Python 3, Django может сериализовать следующее только в Python 3 (непривязанный метод в теле класса), но не может в Python 2:

Для Python 2 мы рекомендуем вынести методы, которые используются как значения для upload_to или других подобных параметров, принимающих функции (например default ), в тело модуля.

Метод deconstruct()¶

Метод deconstruct() собственных полей немного отличается, он должен возвращать кортеж из четырех элементов.

Django запишет полученное значение, как инициализацию для всего класса с заданными аргументами, аналогично тому, как это делается для встроенных полей.

Если все аргументы вашего класса сериализируемые, то для автоматического создания метода вы можете использовать декоратор класса @deconstructible из django.utils.deconstruct :

Обновление с South¶

Если вы уже используете South для миграций, то обновиться до django.db.migrations будет просто:

Убедитесь, что все установки проекта используют последнюю версию миграций

Это всё! Единственной проблемой могут стать циклические внешние ключи. В этом случае makemigrations может создать несколько начальных миграций и вам необходимо самостоятельно пометить их как выполненные:

Сторонние библиотеки и приложения¶

Если вы разрабатываете библиотеку или приложение и хотите поддерживать как миграции South (для Django 1.6 и ниже) так и Django (для 1.7 и выше), вам необходимо предоставлять параллельно два набора миграций в вашем приложении.

Источник

Миграции¶

Команды¶

Есть несколько команд, которые вы будете использовать для взаимодействия с миграциями и обработкой Django схемы базы данных:

Файлы миграции для каждого приложения находятся в каталоге «migrations» внутри этого приложения и предназначены для передачи и распространения как часть его кодовой базы. Вы должны сделать их один раз на своей машине разработки, а затем запустить те же миграции на машинах ваших коллег, ваших промежуточных машинах и, в конечном итоге, ваших производственных машинах.

Миграции будут выполняться одинаково с одним и тем же набором данных и давать согласованные результаты, а это означает, что то, что вы видите при разработке и промежуточном этапе, при одних и тех же обстоятельствах будет именно тем, что произойдет в производственной среде.

Поддержка бэкендов.¶

Миграции поддерживаются на всех бэкэндах, с которыми поставляется Django, а также в любых сторонних бэкэндах, если они запрограммированы на поддержку изменения схемы (выполняется с помощью класса SchemaEditor ).

Однако некоторые базы данных более эффективны, чем другие, когда дело доходит до миграции схемы; некоторые из предостережений описаны ниже.

PostgreSQL¶

MySQL¶

MySQL не поддерживает транзакции, связанные с операциями изменения схемы, а это означает, что, если миграцию не удастся применить, вам придется вручную отменить выбор изменений, чтобы повторить попытку (невозможно вернуться к более ранней точке).

Наконец, MySQL имеет относительно небольшие ограничения на длину имен для столбцов, таблиц и индексов, а также ограничение на общий размер всех столбцов, охватываемых индексом. Это означает, что индексы, которые возможны на других серверах, не будут созданы в MySQL.

SQLite¶

В SQLite небольшие возможности встроенной поддержки изменения схемы, поэтому Django пытается имитировать ее:

Этот процесс обычно работает хорошо, но может быть медленным и иногда давать сбои. Не рекомендуется запускать и переносить SQLite в производственной среде, если вы не очень осведомлены о рисках и его ограничениях; поддержка, с которой поставляется Django, позволяет разработчикам использовать SQLite на своих локальных машинах для разработки менее сложных проектов Django без необходимости в полной базе данных.

Главное¶

Когда у вас есть новые файлы миграции, вы должны применить их к своей базе данных, чтобы убедиться, что они работают должным образом:

Контроль версий¶

Поскольку миграции хранятся в системе управления версиями, вы иногда будете сталкиваться с ситуациями, когда вы и другой разработчик одновременно выполняете миграцию в одно и то же приложение, что приводит к двум миграциям с одинаковым номером.

Финансовые транзакции¶

В базах данных, поддерживающих транзакции DDL (SQLite и PostgreSQL), все операции миграции по умолчанию будут выполняться внутри одной транзакции. Напротив, если база данных не поддерживает транзакции DDL (например, MySQL, Oracle), все операции будут выполняться без транзакции.

Зависимости¶

This means that when you run the migrations, the authors migration runs first and creates the table the ForeignKey references, and then the migration that makes the ForeignKey column runs afterward and creates the constraint. If this didn’t happen, the migration would try to create the ForeignKey column without the table it’s referencing existing and your database would throw an error.

Файлы миграции¶

Миграции сохраняются в формате на диске, называемом здесь «файлами миграции». Эти файлы на самом деле являются обычными файлами Python с согласованным макетом объектов, написанными в декларативном стиле.

Базовый файл миграции выглядит так:

Вам редко, если вообще когда-либо, нужно редактировать файлы миграции вручную, но вполне возможно записать их вручную, если нужно. Некоторые из более сложных операций не обнаруживаются автоматически и доступны только через ручную миграцию, поэтому не бойтесь редактировать их при необходимости.

Пользовательские поля¶

Менеджеры модели¶

Если вы используете функцию from_queryset() для динамического создания класса менеджера, вам необходимо наследовать от сгенерированного класса, чтобы сделать его импортируемым:

Пожалуйста, обратитесь к примечаниям о Исторические модели в миграциях, чтобы увидеть возможные последствия.

Начальные миграции¶

Первоначальные миграции помечаются атрибутом класса initial=True в классе миграции. Если initial атрибут класса не найден, миграция будет считаться «начальной», если это первая миграция в приложении (т.е. если она не зависит от какой-либо другой миграции в том же приложении).

Согласованность истории¶

Как обсуждалось ранее, вам может потребоваться вручную линеаризовать миграции при объединении двух ветвей разработки. При редактировании зависимостей миграции вы можете непреднамеренно создать несогласованное состояние истории, когда миграция была применена, но некоторые из ее зависимостей нет. Это явный признак того, что зависимости неверны, поэтому Django откажется выполнять миграции или делать новые миграции, пока они не будут исправлены. При использовании нескольких баз данных вы можете использовать метод allow_migrate() из маршрутизация баз данных для контроля того, для каких баз данных makemigrations проверяет согласованную историю.

Добавление миграций в приложения¶

Новые приложения предварительно настроены для принятия миграций, поэтому вы можете добавить миграции, запустив makemigrations после внесения некоторых изменений.

Если в вашем приложении уже есть модели и таблицы базы данных и еще нет миграций (например, вы создали его для предыдущей версии Django), вам необходимо преобразовать его для использования миграции, запустив:

Обратите внимание, что это работает только с учетом двух вещей:

Отмена миграций¶

Если вы хотите отменить все миграции, примененные к приложению, используйте имя zero :

Миграция необратима, если она содержит какие-либо необратимые операции. Попытка отменить такие миграции вызовет ошибку IrreversibleError :

Исторические модели¶

Когда вы запускаете миграции, Django работает с историческими версиями ваших моделей, хранящимися в файлах миграции. Если вы пишете код Python с помощью операции RunPython или если у вас есть методы allow_migrate на маршрутизаторах базы данных, вам необходимо использовать эту историческую модель версии, а не импортировать их напрямую.

Если вы импортируете модели напрямую, а не используете исторические модели, ваши миграции могут работать изначально, но не будут работать в будущем, когда вы попытаетесь повторно запустить старые миграции (обычно, когда вы настраиваете новую установку и выполняете все миграции для настройки базы данных).

Это означает, что проблемы исторической модели могут быть не сразу очевидны. Если вы столкнетесь с такой ошибкой, можно отредактировать миграцию, чтобы использовать исторические модели, а не прямой импорт, и зафиксировать эти изменения.

Поскольку сериализовать произвольный код Python невозможно, в этих исторических моделях не будет никаких пользовательских методов, которые вы определили. Однако у них будут одинаковые поля, отношения, менеджеры (только те, у которых есть use_in_migrations = True ) и опции Meta (также версионные, поэтому они могут отличаться от ваших текущих).

Кроме того, конкретные базовые классы модели хранятся как указатели, поэтому вы всегда должны сохранять базовые классы, пока существует миграция, которая содержит ссылку на них. С другой стороны, методы и менеджеры этих базовых классов обычно наследуются, поэтому, если вам абсолютно необходим доступ к ним, вы можете переместить их в суперкласс.

Чтобы удалить старые ссылки, вы можете использовать squash migrations или, если ссылок немного, скопировать их в файлы миграции.

Рекомендации при удалении полей модели¶

Подобно «ссылкам на исторические функции», описанным в предыдущем разделе, удаление настраиваемых полей модели из вашего проекта или стороннего приложения вызовет проблему, если на них есть ссылки в старых миграциях.

Добавьте атрибут system_check_deprecated_details в поле вашей модели, как показано ниже:

После периода устаревания по вашему выбору (два или три выпуска функций для полей в самом Django) измените атрибут system_check_deprecated_details на system_check_removed_details и обновите словарь, аналогичный:

Миграция данных¶

Помимо изменения схемы базы данных, вы также можете использовать миграции для изменения данных в самой базе данных в сочетании со схемой, если хотите.

Миграции, которые изменяют данные, обычно называют «миграциями данных»; их лучше всего записывать как отдельные миграции, расположенные рядом с миграциями вашей схемы.

Для начала создайте пустой файл миграции, с которым вы можете работать (Django поместит файл в нужное место, предложит имя и добавит зависимости за вас):

Затем откройте файл; это должно выглядеть примерно так:

Напишем миграцию, которая заполняет наше новое поле name комбинированными значениями first_name и last_name (мы опомнились и поняли, что не у всех есть имя и фамилия). Все, что нам нужно сделать, это использовать историческую модель и перебирать строки:

Как только это будет сделано, мы можем запустить python manage.py migrate как обычно, и миграция данных будет выполняться на месте вместе с другими миграциями.

Доступ к моделям из других приложений¶

Более продвинутые миграции¶

Сжатие миграций¶

Вам предлагается свободно выполнять миграции и не беспокоиться о том, сколько их у вас; код миграции оптимизирован для работы с сотнями одновременно без особого замедления. Однако, в конце концов, вы захотите вернуться от нескольких сотен миграций к нескольким, и именно здесь на помощь приходит сжатие.

Эти файлы помечены, чтобы сказать, что они заменяют ранее сжатые миграции, поэтому они могут сосуществовать со старыми файлами миграции, и Django будет разумно переключаться между ними в зависимости от того, где вы находитесь в истории. Если вы все еще частично прошли набор миграций, которые вы сжали, он будет продолжать использовать их, пока не достигнет конца, а затем переключится на сжатую историю, в то время как новые установки будут использовать новую сжатую миграцию и пропустить все старые.

Затем вы должны перевести сжатую миграцию на нормальную миграцию:

После того, как вы отменили миграцию, вам не следует повторно сжимать эту сжатую миграцию, пока вы полностью не перейдете на нормальную миграцию.

Сериализация значений¶

Django может сериализовать следующее:

Django не может сериализовать:

Пользовательские сериализаторы¶

Вы можете сериализовать другие типы, написав собственный сериализатор. Например, если бы Django не сериализовал Decimal по умолчанию, вы могли бы сделать это:

Метод serialize() вашего сериализатора должен возвращать строку о том, как значение должно отображаться в миграциях, и набор любых операций импорта, которые необходимы в миграции.

Добавление метода deconstruct() ¶

Django запишет значение как экземпляр вашего класса с заданными аргументами, аналогично тому, как он записывает ссылки на поля Django.

Поддержка нескольких версий Django¶

Если вы поддерживаете стороннее приложение с моделями, вам может потребоваться отправить миграции, поддерживающие несколько версий Django. В этом случае вы всегда должны запускать makemigrations с самой низкой версией Django, которую вы хотите поддерживать.

Система миграции будет поддерживать обратную совместимость в соответствии с той же политикой, что и остальная часть Django, поэтому файлы миграции, созданные в Django X.Y, должны работать без изменений в Django X.Y+1. Однако система миграции не обещает прямой совместимости. Могут быть добавлены новые функции, а файлы миграции, созданные с помощью более новых версий Django, могут не работать в более старых версиях.

Справочник по операциям миграции Охватывает API операций схемы, специальные операции и написание собственных операций. Практическое руководство по написанию миграции Объясняет, как структурировать и записывать миграции базы данных для различных сценариев, с которыми вы можете столкнуться.

Источник

Миграции¶

Команды¶

Есть несколько команд, которые вы будете использовать для взаимодействия с миграциями и обработкой Django схемы базы данных:

Файлы миграции для каждого приложения находятся в каталоге «migrations» внутри этого приложения и предназначены для передачи и распространения как часть его кодовой базы. Вы должны сделать их один раз на своей машине разработки, а затем запустить те же миграции на машинах ваших коллег, ваших промежуточных машинах и, в конечном итоге, ваших производственных машинах.

Миграции будут выполняться одинаково с одним и тем же набором данных и давать согласованные результаты, а это означает, что то, что вы видите при разработке и промежуточном этапе, при одних и тех же обстоятельствах будет именно тем, что произойдет в производственной среде.

Поддержка бэкэндов¶

Миграции поддерживаются на всех бэкэндах, с которыми поставляется Django, а также в любых сторонних бэкэндах, если они запрограммированы на поддержку изменения схемы (выполняется с помощью класса SchemaEditor ).

Однако некоторые базы данных более эффективны, чем другие, когда дело доходит до миграции схемы; некоторые из предостережений описаны ниже.

PostgreSQL¶

MySQL¶

MySQL не поддерживает транзакции, связанные с операциями изменения схемы, а это означает, что, если миграцию не удастся применить, вам придется вручную отменить выбор изменений, чтобы повторить попытку (невозможно вернуться к более ранней точке).

Наконец, MySQL имеет относительно небольшие ограничения на длину имен для столбцов, таблиц и индексов, а также ограничение на общий размер всех столбцов, охватываемых индексом. Это означает, что индексы, которые возможны на других серверах, не будут созданы в MySQL.

SQLite¶

В SQLite небольшие возможности встроенной поддержки изменения схемы, поэтому Django пытается имитировать ее:

Этот процесс обычно работает хорошо, но может быть медленным и иногда давать сбои. Не рекомендуется запускать и переносить SQLite в производственной среде, если вы не очень осведомлены о рисках и его ограничениях; поддержка, с которой поставляется Django, позволяет разработчикам использовать SQLite на своих локальных машинах для разработки менее сложных проектов Django без необходимости в полной базе данных.

Рабочий процесс¶

Когда у вас есть новые файлы миграции, вы должны применить их к своей базе данных, чтобы убедиться, что они работают должным образом:

Контроль версий¶

Поскольку миграции хранятся в системе управления версиями, вы иногда будете сталкиваться с ситуациями, когда вы и другой разработчик одновременно выполняете миграцию в одно и то же приложение, что приводит к двум миграциям с одинаковым номером.

Зависимости¶

Файлы миграции¶

Миграции сохраняются в формате на диске, называемом здесь «файлами миграции». Эти файлы на самом деле представляют собой обычные файлы Python с согласованным макетом объектов, написанные в декларативном стиле.

Базовый файл миграции выглядит так:

Вам редко, если вообще когда-либо, нужно редактировать файлы миграции вручную, но вполне возможно записать их вручную, если нужно. Некоторые из более сложных операций не обнаруживаются автоматически и доступны только через ручную миграцию, поэтому не бойтесь редактировать их при необходимости.

Пользовательские поля¶

Менеджеры модели¶

Если вы используете функцию from_queryset() для динамического создания класса менеджера, вам необходимо наследовать от сгенерированного класса, чтобы сделать его импортируемым:

Пожалуйста, обратитесь к примечаниям о Исторические модели в миграциях, чтобы увидеть возможные последствия.

Начальные миграции¶

Первоначальные миграции помечаются атрибутом класса initial=True в классе миграции. Если initial атрибут класса не найден, миграция будет считаться «начальной», если это первая миграция в приложении (т.е. если она не зависит от какой-либо другой миграции в том же приложении).

Согласованность истории¶

Как обсуждалось ранее, вам может потребоваться вручную линеаризовать миграции при объединении двух ветвей разработки. При редактировании зависимостей миграции вы можете непреднамеренно создать несогласованное состояние истории, когда миграция была применена, но некоторые из ее зависимостей нет. Это явный признак того, что зависимости неверны, поэтому Django откажется выполнять миграции или делать новые миграции, пока они не будут исправлены. При использовании нескольких баз данных вы можете использовать метод allow_migrate() из маршрутизация баз данных для контроля того, для каких баз данных makemigrations проверяет согласованную историю.

Добавление миграций в приложения¶

Если в вашем приложении уже есть модели и таблицы базы данных и еще нет миграций (например, вы создали его в предыдущей версии Django), вам необходимо преобразовать его для использования миграции; это простой процесс:

Обратите внимание, что это работает только с учетом двух вещей:

Отмена миграций¶

Если вы хотите отменить все миграции, примененные к приложению, используйте имя zer :

Исторические модели¶

Когда вы запускаете миграции, Django работает с историческими версиями ваших моделей, хранящимися в файлах миграции. Если вы пишете код Python с помощью операции RunPython или если у вас есть методы allow_migrate на маршрутизаторах базы данных, вам необходимо использовать эту историческую модель версии, а не импортировать их напрямую.

Если вы импортируете модели напрямую, а не используете исторические модели, ваши миграции могут работать изначально, но не будут работать в будущем, когда вы попытаетесь повторно запустить старые миграции (обычно, когда вы настраиваете новую установку и выполняете все миграции для настройки базы данных).

Это означает, что проблемы исторической модели могут быть не сразу очевидны. Если вы столкнетесь с такой ошибкой, можно отредактировать миграцию, чтобы использовать исторические модели, а не прямой импорт, и зафиксировать эти изменения.

Поскольку сериализовать произвольный код Python невозможно, в этих исторических моделях не будет никаких пользовательских методов, которые вы определили. Однако у них будут одинаковые поля, отношения, менеджеры (только те, у которых есть use_in_migrations = True ) и опции Meta (также версионные, поэтому они могут отличаться от ваших текущих).

Кроме того, конкретные базовые классы модели хранятся как указатели, поэтому вы всегда должны сохранять базовые классы, пока существует миграция, которая содержит ссылку на них. С другой стороны, методы и менеджеры этих базовых классов обычно наследуются, поэтому, если вам абсолютно необходим доступ к ним, вы можете переместить их в суперкласс.

Чтобы удалить старые ссылки, вы можете использовать squash migrations или, если ссылок немного, скопировать их в файлы миграции.

Рекомендации при удалении полей модели¶

Подобно «ссылкам на исторические функции», описанным в предыдущем разделе, удаление настраиваемых полей модели из вашего проекта или стороннего приложения вызовет проблему, если на них есть ссылки в старых миграциях.

Добавьте атрибут system_check_deprecated_details в поле вашей модели, как показано ниже:

После периода устаревания по вашему выбору (два или три выпуска функций для полей в самом Django) измените атрибут system_check_deprecated_details на system_check_removed_details и обновите словарь, аналогичный:

Миграция данных¶

Помимо изменения схемы базы данных, вы также можете использовать миграции для изменения данных в самой базе данных в сочетании со схемой, если хотите.

Миграции, которые изменяют данные, обычно называют «миграциями данных»; их лучше всего записывать как отдельные миграции, расположенные рядом с миграциями вашей схемы.

Для начала создайте пустой файл миграции, с которым вы можете работать (Django поместит файл в нужное место, предложит имя и добавит зависимости за вас):

Затем откройте файл; это должно выглядеть примерно так:

Давайте напишем простую миграцию, которая заполняет наше новое поле name комбинированными значениями first_name и last_name (мы пришли в себя и поняли, что не у всех есть имя и фамилия). Все, что нам нужно сделать, это использовать историческую модель и перебирать строки:

Как только это будет сделано, мы можем просто запустить python manage.py migrate как обычно, и миграция данных будет выполняться вместе с другими миграциями.

Доступ к моделям из других приложений¶

Более продвинутые миграции¶

Сжатие миграций¶

Вам предлагается свободно выполнять миграции и не беспокоиться о том, сколько их у вас; код миграции оптимизирован для работы с сотнями одновременно без особого замедления. Однако, в конце концов, вы захотите вернуться от нескольких сотен миграций к нескольким, и именно здесь на помощь приходит сжатие.

Эти файлы помечены, чтобы сказать, что они заменяют ранее сжатые миграции, поэтому они могут сосуществовать со старыми файлами миграции, и Django будет разумно переключаться между ними в зависимости от того, где вы находитесь в истории. Если вы все еще на полпути через набор миграций, которые вы сжали, он будет продолжать использовать их, пока не достигнет конца, а затем переключится на сжатую историю, в то время как новые установки будут просто использовать новую сжатую миграцию и пропускать все старые.

Затем вы должны перевести сжатую миграцию на нормальную миграцию:

После того, как вы отменили миграцию, вам не следует повторно сжимать эту сжатую миграцию, пока вы полностью не перейдете на нормальную миграцию.

Сериализация значений¶

Django может сериализовать следующее:

Django не может сериализовать:

Пользовательские сериализаторы¶

Вы можете сериализовать другие типы, написав собственный сериализатор. Например, если бы Django не сериализовал Decimal по умолчанию, вы могли бы сделать это:

Метод serialize() вашего сериализатора должен возвращать строку о том, как значение должно отображаться в миграциях, и набор любых операций импорта, которые необходимы в миграции.

Добавление метода deconstruct() ¶

Django запишет значение как экземпляр вашего класса с заданными аргументами, аналогично тому, как он записывает ссылки на поля Django.

Поддержка нескольких версий Django¶

Если вы поддерживаете стороннее приложение с моделями, вам может потребоваться отправить миграции, поддерживающие несколько версий Django. В этом случае вы всегда должны запускать makemigrations с самой низкой версией Django, которую вы хотите поддерживать.

Система миграции будет поддерживать обратную совместимость в соответствии с той же политикой, что и остальная часть Django, поэтому файлы миграции, созданные в Django X.Y, должны работать без изменений в Django X.Y+1. Однако система миграции не обещает прямой совместимости. Могут быть добавлены новые функции, а файлы миграции, созданные с помощью более новых версий Django, могут не работать в более старых версиях.

Справочник по операциям миграции Охватывает API операций схемы, специальные операции и написание собственных операций. Практическое руководство по написанию миграции Объясняет, как структурировать и записывать миграции базы данных для различных сценариев, с которыми вы можете столкнуться.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *