1

多かれ少なかれ列挙型として機能する CharField を持つモデルがあります。

grade = models.CharField(max_length='1', choices=('A', 'B', 'C'))

残念ながら、やや複雑な理由から、次のように SmallIntegerField に移行する必要があります。

grade = models.SmallIntegerField(choices=(1, 2, 3))

南でこれを行うにはどうすればよいですか?いくつかの一般的なアイデアがありますが、それらを実行する方法が正確にはわかりません。私の最初の考えは、一連の移行です。

  1. 新しいgrade_newSmallIntegerField を追加し、古い等級をその中の新しい等級に変換します (移行の forward メソッド中)。
  2. grade同時に名前grade_newを変更しながら古いフィールドを削除しますgrade

これは正しいアプローチですか?もしそうなら、ステップ 1 で古いグレードを新しいグレードに変換するにはどうすればよいですか?

4

1 に答える 1

2

このアプローチが正しいものであるかどうかを知りたいと思っていますが、2 回の移行/コミットだけで上記の計画を実行する方法を理解することができました。

まず、モデルにフィールドを追加しnew_grade = models.SmallIntegerField(choices=(1, 2, 3))(enum vars を複製する必要がありました) 、モデルのクラスのおよびフィールドgradeへの参照を更新しました。new_gradeorderingunique_togetherMeta

class Foo(models.Model):
  A, B, C = 'A', 'B', 'C'
  A2, B2, C2, = 1, 2, 3
  grade = models.CharField(max_length='1', choices=((A, 'A'), (B, 'B'), (C, 'C')))
  new_grade = models.SmallIntegerField(choices=((A2, 1), (B2, 2), (C2, 3)))

  class Meta:
    ordering = ['x', 'new_grade']
    unique_together = ('x', 'new_grade')

を実行した後manage.py schemamigration app --auto、移行ファイルを開き、転送方法を次のように変更しました。

def forwards(self, orm):
  # For the unique_together...
  db.delete_unique('app_foo', ['x', 'grade'])

  db.add_column('app_foo', 'new_grade',
                self.gf('django.db.models.fields.SmallIntegerField')(default=1),
                keep_default=False)
  if not db.dry_run:
    mapping = {'A': 1, 'B': 2, 'C': 3}
    for foo in orm.Foo.objects.all():
      foo.new_grade = mapping[foo.grade]
      foo.save()

  # For the unique_together...
  db.create_unique('app_foo', ['x', 'new_grade'])

を実行した後manage.py migrate app、すべての Foo に、マッピングされた値を持つ重複した new_grade フィールドが含まれるようになりました。その時点で、安定した状態だったので、コードをコミットしました。

次に、models.py で古いgradeフィールドを削除し、重複する列挙変数の名前を変更new_gradeし、Metaクラス内の参照を再度更新しました。

class Foo(models.Model):
  A, B, C, = 1, 2, 3
  grade = models.SmallIntegerField(choices=((A, 1), (B, 2), (C, 3)))

  class Meta:
    ordering = ['x', 'grade']
    unique_together = ('x', 'grade')

もう一度実行manage.py schemamigration app --autoして移行ファイルを開き、 forward メソッドを次のように変更しました。

def forwards(self, orm):
  # For the unique_together...
  db.delete_unique('app_foo', ['x', 'new_grade'])

  db.delete_column('app_foo', 'grade')
  db.rename_column('app_foo', 'new_grade', 'grade')

  # For the unique_together...
  db.create_unique('app_foo', ['x', 'grade'])

を実行するmanage.py migrate appと、すべての Foo のgradeフィールドが以前のフィールドに置き換えられnew_grade、移行が完了しました。

于 2013-05-31T06:22:49.577 に答える