2011-09-07 29 views
16

私はDjangoアプリケーションでSouthを使用しています。私はForeignKeyの関係からOneToOneFieldの関係に変化している2つのモデルを持っています。私のdevデータベースでこの移行を実行したとき、うまくいきました。テストデータベースを作成する際にマイグレーションが実行されると、「mydb。#sql-3249_1d(errno:121)」テーブルを作成できません。いくつかのGoogle検索を行うと、これは通常、既存の制約と同じ名前の制約を追加しようとすると問題になることが明らかになりました。それが失敗し、移行中の特定の行は次のとおりです。Django - ForeignKeyの関係をOneToOneに変更する

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']) 

class MyModel(models.Model): 
    othermodel = models.ForeignKey(OtherModel) 

移行で次の文を生成

class MyModel(models.Model): 
    othermodel = models.OneToOneField(OtherModel) 

へ:

関係をから変更されました

create_uniqueコールに失敗する代わりに、01で失敗していますが呼び出されます。

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を削除する場合:私は、生成されていたものをSQL参照するには、次のコマンドを実行しました私は--db-dry-runとそれを実行すると、SQLは生成されませんが、私はそれを実際に実行すると、私はまだエラーが発生します。

私はここで紛失していますが、何か助けていただければ幸いです。

+1

私はいくつかの日前とまったく同じ移行を作成し、それがうまく走りました。別のデータベースバックエンドで同じコードを試すことができますか(私はPostgreSQLデータベース上でそれをやった)。 また、あなたの南のバージョンを確認してください。 – emyller

+0

私は助けてくれました - 私は変更を加え、同じPythonとSQLコードを生成し、移行はmysql 5.1.56 for win32を使って正常に実行されました。 – Hannele

+0

サウスメーリングリストでこれを尋ねると、その答えが見つかる可能性が高いです。 –

答えて

0

私が試してみようとする最初のことは、私がそれをハックできるかどうかを確認するために様々な場所にdb.delete_unique(...)を追加することです。私は3つのマイグレーションにそれを分割したい、という失敗

  1. OneToOne
  2. のために上の古い列からすべてのFK値をコピーするデータ移行を新しい列を追加するためのスキーマの移行新しい
  3. 古い列を削除するためのスキーマ移行。新しい列の名前を古いものと同じ名前に変更するコマンドを手動で編集することにしました。
11

実際に移行する必要はありません。 OneToOneとForeignKeyの関係には、フックの下で互換性のあるデータベーススキーマがあります。テーブルの1つにある他のオブジェクトIDを持つ単純な列。

この変更を無視するように南に指示したくない場合は、ちょうどmigrate --fakeで移行を偽装してください。

+0

そして、あなたが疑問に思っていることは、@ e-satisがこれについて正しいのであれば、コード( 'django.db.models.fields.related')からこの小物を取ってください:" OneToOneFieldは基本的にForeignKeyと同じです例外はありますが、常に「独自の」制約が付いています」OneToOneは実際にはわずかな微調整だけでForeignKeyを継承していることに注意してください。 – mlissner

+0

正確には、ForeignKeyからOneToOneFieldにフィールドを変更すると、スキップしてはならないデータベース(少なくとも制約をサポートしているものであれば)に影響があります:ForeignKeyは一意ではなくOneToOneFieldです。 Django 1.8では、mysqlバックエンドでネイティブコマンド 'makemigrations'を使用していましたが、全く問題はありませんでした。マイグレーションにより、DBレベルのフィールド上の以前の非ユニーク・インデックスが正しく削除され、新しいユニーク・インデックスが設定されました。 – baxeico

1

ここでの目標はマイグ​​レーションを偽造することですが、私はあなたがチームで働いている場合は別のアプローチを提案します。

移行を作成する場合、--fakeを作成すると、すべてのチームメンバーが--fakeに覚えておく必要があります。彼らがアップグレードするときにこれをしないと、あなたは困っています。

より良いアプローチは、それを移行した後、空の移行を作成することです:

manage.py schemamigration yourapp --empty fake_migration_of_foreign_key_to_onetoone 
manage.py migrate # Like you always do! 
関連する問題