Django - 将ForeignKey关系更改为OneToOne

时间:2011-09-07 23:50:17

标签: python mysql django django-south

我正在使用South和我的Django应用程序。我有两个模型,我从ForeignKey关系变为OneToOneField关系。当我在我的dev数据库上运行此迁移时,它运行正常。当迁移作为创建测试数据库的一部分运行时,最新的迁移失败,出现MySQL 1005错误:“无法创建表mydb。#sql-3249_1d(错误号:121)”。做一些谷歌搜索显示,这通常是尝试添加与现有约束具有相同名称的约束的问题。它失败的迁移中的特定行是:

关系改变自:

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 个答案:

答案 0 :(得分:11)

您实际上根本不需要迁移。 OneToOne和ForeignKey关系在钩子下有一个兼容的数据库模式:一个简单的列,其中一个表中包含另一个对象ID。

如果您不想告诉南方忽略此更改,请假装使用migrate --fake进行迁移。

答案 1 :(得分:1)

我同意@ e-satisf,这里的目标是假冒迁移,但如果您与团队合作,我建议采用不同的方法。

如果您创建迁移,然后--fake,则您的所有团队成员都需要记住--fake它。如果他们中的任何人在升级时没有这样做,那你就麻烦了。

更好的方法是创建一个空迁移,然后迁移它:

manage.py schemamigration yourapp --empty fake_migration_of_foreign_key_to_onetoone
manage.py migrate  # Like you always do! 

答案 2 :(得分:0)

我要尝试的第一件事就是在不同的地方添加一个db.delete_unique(...),看看我是否可以破解它。

如果做不到这一点,我会把它分成3次迁移:

  1. 为OneToOne添加新列的架构迁移
  2. 将所有FK值从旧列复制到新
  3. 的数据迁移
  4. 删除旧列的架构迁移,然后我手动编辑以包含将新列重命名为旧列的命令。