このアプローチが正しいものであるかどうかを知りたいと思っていますが、2 回の移行/コミットだけで上記の計画を実行する方法を理解することができました。
まず、モデルにフィールドを追加しnew_grade = models.SmallIntegerField(choices=(1, 2, 3))
(enum vars を複製する必要がありました) 、モデルのクラスのおよびフィールドgrade
への参照を更新しました。new_grade
ordering
unique_together
Meta
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
、移行が完了しました。