Django:使用South将CharField枚举迁移到SmallIntegerField

时间:2013-05-31 04:45:49

标签: django django-south database-migration

我有一个CharField或多或少作为枚举的模型:

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

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

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

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

  1. 添加一个新的grade_new SmallIntegerField,并将旧成绩翻译为其中的新成绩(在迁移'正向方法期间)。
  2. 删除旧的grade字段,同时将grade_new重命名为grade
  3. 这是正确的做法吗?如果是这样,我将如何在步骤#1中将旧成绩翻译成新成绩?

1 个答案:

答案 0 :(得分:2)

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

首先,我在模型中添加了new_grade = models.SmallIntegerField(choices=(1, 2, 3))字段(需要复制枚举变量),并将grade中对new_grade的引用更新为ordering和{ {1}}模型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']) 后,所有Foos现在都有一个带有映射值的重复new_grade字段。那时我提交了我的代码,因为它处于稳定状态。

其次,在models.py中,我删除了旧的manage.py migrate app字段,重命名了重复的枚举变量,并再次更新了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']) 后,所有Foos现在都将manage.py migrate app字段替换为以前的grade字段,并且迁移已完成!