【问题标题】:Django: Migrate CharField enum to SmallIntegerField using SouthDjango:使用 South 将 CharField 枚举迁移到 SmallIntegerField
【发布时间】:2013-05-26 20:08:28
【问题描述】:

我有一个模型,其 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_new 重命名为grade

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

【问题讨论】:

    标签: django django-south database-migration


    【解决方案1】:

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

    首先,我向模型添加了一个new_grade = models.SmallIntegerField(choices=(1, 2, 3)) 字段(这需要复制枚举变量),并将模型@987654326 的orderingunique_together 字段中对grade 的引用更新为new_grade @类:

    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 之后,所有 Foo 现在都有一个重复的带有映射值的 new_grade 字段。那时我提交了我的代码,因为它处于稳定状态。

    其次,在models.py中,我删除了旧的grade字段,重命名了重复的枚举变量,并再次更新了Meta类中对new_grade的引用:

    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 字段,并且迁移完成!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-14
      • 2012-08-06
      • 2012-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-16
      • 2012-03-03
      相关资源
      最近更新 更多