Django - изменение отношения ForeignKey к OneToOne
Я использую Юг с моим приложением Django. У меня есть две модели, которые я изменяю от отношения ForeignKey
к отношению OneToOneField
. Когда я запускал эту миграцию в моей базе данных dev, она работала нормально. Когда миграция запускается как часть создания тестовой базы данных, последняя миграция завершается с ошибкой MySQL 1005: "Невозможно создать таблицу mydb. # Sql-3249_1d (errno: 121)". Выполнение какого-то Googling показало, что это обычно проблема с попыткой добавить ограничение с тем же именем, что и существующее ограничение. Конкретной линией миграции, с которой он выходит, является:
Отношение было изменено с:
class MyModel(models.Model):
othermodel = models.ForeignKey(OtherModel)
к
class MyModel(models.Model):
othermodel = models.OneToOneField(OtherModel)
который сгенерировал следующие операторы миграции:
db.alter_column('myapp_mymodel', 'othermodel_id', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['myapp.OtherModel'], unique=True))
db.create_unique('myapp_mymodel', ['othermodel_id'])
Но вместо отказа при вызове create_unique
он не работает при вызове alter_column
. Я выполнил следующую команду, чтобы увидеть, какой SQL был сгенерирован:
python manage.py migrate myapp 0010 --db-dry-run --verbosity=2
и распечатал
myapp:0010_auto__chg_field_mymodel_othermodel__add_unique_mymodel
= ALTER TABLE `myapp_mymodel` ADD CONSTRAINT `myapp_mymodel_othermodel_id_uniq` UNIQUE (`othermodel_id`) []
= SET FOREIGN_KEY_CHECKS=1; []
= ALTER TABLE `myapp_mymodel` ADD CONSTRAINT `myapp_mymodel_othermodel_id_uniq` UNIQUE (`othermodel_id`) []
Кажется странным, что он пытается дважды запустить ADD CONSTRAINT
, но если я удалю вызов db.create_unique
, при запуске его с --db-dry-run
SQL не генерируется SQL, но я все равно получаю ошибку, если я запускаю это реально.
Я здесь в затруднении, любая помощь приветствуется.
Ответы
Ответ 1
Вам вообще не нужна миграция. У отношений OneToOne и ForeignKey есть подсистема совместимой базы данных: простой столбец с другим идентификатором объекта в одной из таблиц.
Просто подделайте миграцию с помощью migrate --fake
, если вы не хотите вводить ошибку в том, что говорите югу, чтобы игнорировать это изменение.
Ответ 2
Я согласен с @e-satis, что целью здесь является подделка миграции, но я предлагаю другой подход, если вы работаете с командой.
Если вы создаете миграцию, а затем --fake
, все ваши члены команды должны будут запомнить и --fake
. Если кто-то из них не делает этого, когда они обновляются, у вас проблемы.
Лучший подход - создать пустую миграцию, а затем перенести ее:
manage.py schemamigration yourapp --empty fake_migration_of_foreign_key_to_onetoone
manage.py migrate # Like you always do!
Ответ 3
В первую очередь я бы попытался добавить db.delete_unique(...)
в разные места, чтобы увидеть, могу ли я его взломать.
В противном случае я разделил бы его на 3 миграции:
- миграция схемы для добавления нового столбца для OneToOne
- перенос данных для копирования всех значений FK из старого столбца в новый
- миграция схемы для удаления старого столбца, который затем я вручную отредактировал, чтобы включить команду для переименования нового столбца в прежнее значение.