2013-05-31 4 views
1

У меня есть модель с CharField, действующую более или менее как перечисление:Джанго: Перенести CharField перечисление в SmallIntegerField используя Юг

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

Является ли это правильный подход? И если да, как бы я перевел старые оценки на новые оценки в шаге 1?

ответ

2

Хотя я все еще хотел бы знать, был ли этот подход правильным, я смог выяснить, как выполнить план выше только с двумя миграциями/фиксациями.

Во-первых, я добавил new_grade = models.SmallIntegerField(choices=(1, 2, 3)) поле для модели (которая требует дублирования перечисления вары) и обновленные ссылки на 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, у всех 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, все Foos теперь было их grade поля заменено с прежним полем new_grade и миграция была завершена!

Смежные вопросы