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

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

FieldError: Local field <field_name> in class <child_model> clashes with field of similar name from base class <parent_model>

В тот момент, когда запускаются и makemigrations, и migrate, и возникает эта ошибка, родительская модель больше не отображается в коде как родитель класса, но миграция все еще жалуется.

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

(Упрощенный) подход, который я использовал в South, был следующим:

  1. Удалите модель как родительскую и добавьте новые поля в дочернюю.
  2. Добавьте явное поле первичного ключа с тем же именем, что и у старого автоматического поля *_ptr_id.
  3. Запустите schemamigration и отредактируйте файл следующим образом:

    • Remove South's attempt to remove and recreate the *_ptr field
    • Добавьте некоторую пользовательскую логику, чтобы удалить ForeignKey-ness поля *_ptr_id и добавить PrimaryKey-ness
  4. Используйте datamigration, чтобы получить значения от старого родителя и добавить их в новые поля дочернего элемента.

Я надеялся, что этот подход будет достаточно легко адаптирован к собственным миграциям Django, и я получил (с некоторыми изменениями) логику замены полей *_ptr_id. Но Django не позволяет мне добавлять новые поля. Я пробовал следующее:

  • Удаление родительской модели и выполнение пользовательской замены *_ptr_id, миграция и добавление полей в качестве второй миграции.
  • Удаление родительской модели и не редактирование файла для ручного взаимодействия с *_ptr_id, но сохранение операций удаления/добавления Django и миграция с --fake.

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

У кого-нибудь еще была эта проблема и удалось ее обойти?

Изменить:

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


person oogles    schedule 19.10.2015    source источник


Ответы (1)


Столкнувшись с той же проблемой в Django 1.11, я последовал отредактированному совету и нашел первоначальный вызов «CreateModel» в своих файлах миграции. Комментирование строки bases=('{appname}.{modelname}',), и явная установка первичного ключа моей модели как «id», а затем повторный запуск makemigrations и migrate устранили проблему для меня.

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

Другой вариант для людей, менее вложенных в название своей модели (и данные): переименовать ее при удалении родителя. Обратите внимание, что, хотя это сработало для меня, возврат к исходному имени модели в другой миграции привел к той же ошибке «однажды дочерняя, всегда дочерняя», поэтому вам все равно нужно будет отредактировать строку «bases =» в ваших миграциях.

Спасибо oogles и сообществу!

person Ryan    schedule 31.01.2018
comment
Да, не найдя другой альтернативы и не получив здесь ответа, я также отредактировал эту строку bases. С тех пор никаких побочных эффектов я не замечал. И поскольку я забыл вернуться и ответить на этот вопрос как таковой, вы, сэр, только что заслужили принятый ответ;). - person oogles; 01.02.2018