1

我有一个 CharField 或多或少充当枚举的模型:

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

不幸的是,由于有些复杂的原因,我必须将其迁移为 SmallIntegerField,如下所示:

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

我将如何在南方做到这一点?我有几个一般的想法,但不确定如何执行它们。我的第一个想法是一系列迁移:

  1. 添加一个新的grade_newSmallIntegerField 并将旧成绩转换为其中的新成绩(在迁移的转发方法期间)。
  2. 删除旧grade字段,同时重命名grade_newgrade

这是正确的方法吗?如果是这样,我将如何在第 1 步中将旧成绩转换为新成绩?

4

1 回答 1

2

虽然我仍然很想知道这种方法是否正确,但我能够弄清楚如何仅通过两次迁移/提交来执行上述计划。

首先,我new_grade = models.SmallIntegerField(choices=(1, 2, 3))在模型中添加了一个字段(这需要复制枚举变量),并更新了模型类的和字段中对gradeto的引用: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打开迁移文件,修改forward方法为:

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,所有 Foos 现在都有一个带有映射值的重复 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并打开迁移文件将转发方法修改为:

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 回答