4

2 つのモデルを作成したとします。

class Car(models.Model):
    name =  models.CharField(max_length=50)
    size =  models.IntegerField()


class Manufacturer(models.Model):
    name =  models.CharField(max_length=50)
    country =  models.CharField(max_length=50)
    car = models.ManyToManyField(Car)

両方のモデルにエントリを追加したところ、各 Car が固有のメーカーにのみ関連していることに気付きました。したがって、ManyToManyField を ForeignKey に変換する必要があります。

class Car(models.Model):
    name =  models.CharField(max_length=50)
    size =  models.IntegerField()
    manufacturer = models.ForeignKey(Manufacturer)

class Manufacturer(models.Model):
    name =  models.CharField(max_length=50)
    country =  models.CharField(max_length=50)

エントリを失うことなくそれを行うにはどうすればよいですか? Southのドキュメントを調べてみましたが、この変換方法は見つかりませんでした...

4

2 に答える 2

7

これは自明ではありません。次の 3 つの移行が必要になると思います。

  1. を追加しForeignKeyます。
  2. ManyToManyForeignKey(forwardsメソッドを使用して)に変換します。
  3. を取り外しますManyToMany

1 と 2、または 2 と 3 をマージすることもできますが、お勧めしません。さらに、 2 のメソッド
も実装する必要があります。backwards

2. の例は次forwardsとおりです。

class Migration(SchemaMigration):
    def forwards(self, orm):
        for manufacturer in orm.Manufacturer.objects.all():
             for car in manufacturer.car.all():
                  car.manufacturer = manufacturer
                  car.save()

その点に注意してください:

  • ここにはbackwardsまだ方法がありません。
  • これは広範囲にテストする必要があります: 移行は特に注意する必要があります。
  • 車に 2 つのメーカーがある場合、最後のメーカーが保持されます。
  • これは非常に非効率的です。メーカーごとに車ごとにクエリを実行します。

また、ステップ 2 でこれらの関係を使用するコードを更新する必要があります。 / 3.

于 2012-12-19T13:56:30.580 に答える
6

Thomas Orozco によって提供された優れた回答に基づいて、Django>=1.7 のソリューションを提供したいと思います (基本的に、ポイント 2 ManyToMany を ForeignKey に変換することは、Django の新しいバージョンでは異なります)。したがって、2 番目の移行のコードは次のとおりです。

class Migration(migrations.Migration):

    def migrate_m2m_to_fk(apps, schema_editor):
        Manufacturer = apps.get_model("app", "Manufacturer")
        for manufacturer in Manufacturer.objects.all():
             for car in manufacturer.car.all():
                  car.manufacturer = manufacturer
                  car.save()

    def migrate_fk_to_m2m(apps, schema_editor):
        Car = apps.get_model("app", "Car")
        for c in Car.objects.all():
            if c.manufacturer:
                c.manufacturer.car.add(c)
                c.manufacturer.save()

    operations = [
        migrations.RunPython(migrate_m2m_to_fk, migrate_fk_to_m2m)
    ]

「アプリ」は、モデルが存在する Django アプリです。順方向と逆方向の両方の移行コードが示されています (トーマスが言及しているように、事前に複数の関係が存在していた場合、この移行を実行するとデータが失われる可能性があるため、注意してください)。

于 2016-02-19T16:23:05.307 に答える