4

私はsouth移行を管理するために使用していますが、追い詰められました。基本的に、次の設定があります。

App1

class A(models.Model):
  # bunch of attributes

App2

class B(models.Models):
  instance_a = models.OneToOneField(A, null=True, blank=True, 
                                    editable=False)

今、私はこれからこれに行きたいです:

App1

class A(models.Model):
  instance_b = models.ForeignKey(B, null=True, blank=True)

App2

class B(models.Models):
  # other attributes

私の主な問題は、データを失うことができないということです。したがって、基本的に、移行の最後に、以前にオブジェクトBにマップされたすべてのオブジェクトAは、そのマッピングを維持する必要があります。例として、ID7のオブジェクトAがID8のオブジェクトBにマップされた場合、この手順の終わりまでに、このマッピングを保持する必要があります。

一時的なプレースホルダーとデータの移行を組み合わせたスキーマの移行からいくつかのことを試しました。ただし、私は常に同じ場所にいることになります。つまり、データ移行が実行されるまでに、正しい属性にアクセスするための以前の関係がなくなります。したがって、たとえば、B.instance_aは使用できなくなります。

私は2つのことについてあなたの意見をお願いします:

  • まず、これは南への移動だけを使用して実行可能ですか。
  • 第二に、私はどのように進めましょうか。

ありがとう

4

1 に答える 1

3

ついにしばらくして、他のdjango-south人を助けるかもしれない手順を手に入れました。重要なのは南のdepends_on機能(http://south.aeracode.org/wiki/Dependencies)でした。私は4つのステップでそれをしました:

最初

  • モデルの外部キーの値のプレースホルダーを作成しますA

したがって、モデルは次のAようになります。

class A(models.Model):
    instance_b_placeholder = models.ForeignKey(A, null=True, blank=True)

今すぐ実行しますmanage.py schemamigration app1 --auto

2番

  • 値をコピーできるように、データ移行を作成します。目標は、データベースでデータを複製し、後で属性の名前を変更して古い属性を削除することです。問題manage.py datamigration app1 update_fields。データ移行をで維持することを選択しましたapp1。これを行わない場合は、前回の移行後に実行されることを確認してください。

コード化されたデータ移行は次のとおりです。

# Forwards:

for b in orm['app2.B'].objects.filter(instance_b__isnull=False):
        b.instance_a.instance_b_placeholder = b
        b.instance_a.save()

# Backwards:

for r in orm['app1.A'].objects.filter(instance_b_placeholder__isnull=False):
        r.instance_b_placeholder.instance_a = r
        r.instance_b_placeholder.save()

3番目

  • instance_bモデルからフィールドを削除Bし、前の手順で作成したものの後に移行を実行するようにしてください。

モデルは次のBようになります。

class B(models.Model):
     # etc...

以前の移行を次manage.py schemamigration app2 --autoの場所に追加して、移行を発行および編集します。depends_on

depends_on = (
    ("app1", "<migration_number>_update_fields"),
)

4番目のステップ

  • プレースホルダーの名前を変更します。これは、コード内の名前を変更し、移行を編集することで実現されます。新しい列を削除して追加する傾向があるため、編集が必要ですsouthが、列の名前を変更するだけです。

  • この移行は最後に実行する必要があるため、前の移行に依存させました。

コードは次のとおりです。

depends_on = (
    ("app2", "<previous_migration_here>"),
)

# Forwards:

    db.rename_column('app1_a', 'instance_b_placeholder_id', 'instance_b_id')

# Backwards:

    db.rename_column('app1_a', 'instance_b_id', 'instance_b_placeholder_id')

以上です。他にもたくさんの方法があるかどうかはわかりませんが、少なくともこれは役に立ちました。

于 2012-09-20T20:38:10.210 に答える