@Megadeth77

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

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

Есть модель скажем Model, в ней есть foregin keys на другие модели.

class ModelA: ...
class ModelX: ...

class Model:
  a = models.ForeignKey(ModelA, default=A)
  x = models.ForeignKey(ModelX, default=X)


И вот в один прекрасный момент мы создаем еще одну модель (ModelY) на которую должна ссылаться Model. И при создании Model у объекта должна быть ссылка на какой то дефолтный объект ModelY, которого еще очевидно нет!

class ModelY: ...
class Model:
  y = models.ForeignKey(ModelY, default=??????)


Т.е. последовательность при миграции должна быть такой:
-Создать таблицу ModelY
-Создать в этой таблице дефолтный объект, куда то записать его id
-Создать новое поле в таблице Model, причем дефолтное значение взять из предыдущего пункта

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

Есть какие то best prectice для такого случая ? Или хотя бы по каким ключевым словам гуглить?
  • Вопрос задан
  • 127 просмотров
Решения вопроса 1
@marazmiki
Укротитель питонов
Сценарий для джанги я бы предложил такой:
  1. Создать модель ModelY, сгенерировать и применить соответствующую миграцию.
  2. Добавить в Model необязательный (т.е. null=True) внешний на ModelY. Сгенерировать миграцию и применить её.
  3. Создать дата-миграцию, в которой создадим "дефолтный" объект ModelY. Накатить её.
  4. Изменить внешний ключ (см. п.2) таким образом, чтобы он подставлял дефолтное значение. Пока не убирать null=True. Накатить. Теперь все вновь созданные модели будут создаваться правильно
  5. Создать дата-миграцию, которая заменила бы все нулевые внешние ключи на дефолтный объект. Накатить.
  6. Теперь можно сделать внешний ключ из п.2. обязательным, т.е. убрать null=True.


Что же касается best practices, то из опыта я бы посоветовал следующее:

  • Не надо пытаться минимизировать число миграций или засунуть всё в одну. Напротив, лучше идти по пути упрощения миграций, а не уменьшия их количества.
  • Миграции лучше делать максимально независимыми друг от друга.
  • Не нужно заморачиваться с two-way; если какое-то решение оказалось неудачным, лучше сделать ещё одну миграцию, которая делает противоложную операцию относительно предыдущей, чем откатываться.
  • Если добавляете новое поле, обязательно делайте его сперва null, а лишь потом заполняйте.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы