Django - изменить отношение ForeignKey к OneToOne - PullRequest
16 голосов
/ 08 сентября 2011

Я использую Юг с моим приложением Django.У меня есть две модели, которые я меняю с отношения ForeignKey на отношение OneToOneField.Когда я запустил эту миграцию в своей базе данных dev, она прошла нормально.Когда миграция запускается как часть создания тестовой базы данных, последняя миграция завершается с ошибкой MySQL 1005: «Не удается создать таблицу mydb. # Sql-3249_1d (errno: 121)».Выполнение некоторого поиска в Google показало, что обычно это проблема с попыткой добавить ограничение с тем же именем, что и существующее ограничение.Конкретная строка в миграции, на которой происходит сбой:

Отношение было изменено с:

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 не генерируется, но я все равно получаю сообщение об ошибке, если я запускаю его по-настоящему.

Я в растерянности, любойпомощь приветствуется.

Ответы [ 3 ]

11 голосов
/ 26 ноября 2011

Тебе вообще не нужна миграция. Отношения OneToOne и ForeignKey имеют совместимую схему базы данных под хуком: простой столбец с идентификатором другого объекта в одной из таблиц.

Просто имитируйте миграцию с migrate --fake, если вы не хотите говорить о том, что югу нужно игнорировать это изменение.

1 голос
/ 26 сентября 2013

Я согласен с @ e-обеспечить, что цель состоит в том, чтобы имитировать миграцию, но я предлагаю другой подход, если вы работаете с командой.

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

Лучше всего создать пустую миграцию, а затем перенести ее:

manage.py schemamigration yourapp --empty fake_migration_of_foreign_key_to_onetoone
manage.py migrate  # Like you always do! 
0 голосов
/ 22 сентября 2011

Первое, что я бы попробовал, это добавить db.delete_unique(...) в разные места, чтобы посмотреть, смогу ли я его взломать.

Если это не удастся, я разделю его на 3 миграции:

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