使用South修改模型字段的数据

时间:2014-09-18 00:24:35

标签: django django-models django-south

我有一个我想重命名的模型,但也改变了它的数据。模型字段,例如foo包含字符数据1 ... 6,我想以下列方式映射此数据:

12 - > 1&& 34 - > 2&& 5 - > 3&& 6 - > 4

我在我的应用上convert_to_south创建了0001_initial,然后更改了models.py中的新新字段,并schemamigration创建了0002_initial.py。现在我该如何修改现有数据?以下是我的迁移:

0001_initial

class Migration(SchemaMigration):

    def forwards(self, orm):
        # Adding model 'Applicant'
        db.create_table(u'registrar_applicant', (
            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
            ('registered_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
            ('workshop', self.gf('django.db.models.fields.CharField')(max_length=20)),
            ('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
            ('semester', self.gf('django.db.models.fields.CharField')(max_length=1)),
            ('python_experience', self.gf('django.db.models.fields.CharField')(max_length=1)),
            ('phone_number', self.gf('django.db.models.fields.CharField')(max_length=10, blank=True)),
            ('email', self.gf('django.db.models.fields.EmailField')(max_length=75)),
            ('solved_puzzle', self.gf('django.db.models.fields.BooleanField')(default=False)),
        ))
        db.send_create_signal(u'registrar', ['Applicant'])


    def backwards(self, orm):
        # Deleting model 'Applicant'
        db.delete_table(u'registrar_applicant')


    models = {
        u'registrar.applicant': {
            'Meta': {'ordering': "['-solved_puzzle', 'registered_at', 'semester', 'name']", 'object_name': 'Applicant'},
            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
            'phone_number': ('django.db.models.fields.CharField', [], {'max_length': '10', 'blank': 'True'}),
            'python_experience': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
            'registered_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
            'semester': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
            'solved_puzzle': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
            'workshop': ('django.db.models.fields.CharField', [], {'max_length': '20'})
        }
    }

    complete_apps = ['registrar']

0002_initial

class Migration(SchemaMigration):

    def forwards(self, orm):
        # Adding model 'Applicant'
        db.create_table(u'registrar_applicant', (
            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
            ('registered_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
            ('workshop', self.gf('django.db.models.fields.CharField')(max_length=20)),
            ('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
            ('year', self.gf('django.db.models.fields.CharField')(max_length=1)),
            ('python_experience', self.gf('django.db.models.fields.CharField')(max_length=1)),
            ('phone_number', self.gf('django.db.models.fields.CharField')(max_length=10, blank=True)),
            ('email', self.gf('django.db.models.fields.EmailField')(max_length=75)),
            ('solved_puzzle', self.gf('django.db.models.fields.BooleanField')(default=False)),
        ))
        db.send_create_signal(u'registrar', ['Applicant'])


    def backwards(self, orm):
        # Deleting model 'Applicant'
        db.delete_table(u'registrar_applicant')


    models = {
        u'registrar.applicant': {
            'Meta': {'ordering': "['-solved_puzzle', 'registered_at', 'year', 'name']", 'object_name': 'Applicant'},
            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
            'phone_number': ('django.db.models.fields.CharField', [], {'max_length': '10', 'blank': 'True'}),
            'python_experience': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
            'registered_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
            'solved_puzzle': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
            'workshop': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
            'year': ('django.db.models.fields.CharField', [], {'max_length': '1'})
        }
    }

    complete_apps = ['registrar']

1 个答案:

答案 0 :(得分:1)

为此,您必须创建data migration

# Run this command from the shell
python manage.py datamigration <app_name> change_foo_values

这将创建一个名为0003_change_foo_values.py的迁移文件。您必须手动编辑该文件。

# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models

class Migration(DataMigration):

    def forwards(self, orm):
        "Write your forwards methods here."
        # Note: Don't use "from appname.models import ModelName". 
        # Use orm.ModelName to refer to models in this application,
        # and orm['appname.ModelName'] for models in other applications.
        orm.Applicant.objects.filter(foo__in=['1', '2']).update(foo='1')
        orm.Applicant.objects.filter(foo__in=['3', '4']).update(foo='2')
        orm.Applicant.objects.filter(foo__in=['5', '6']).update(foo='3')

    def backwards(self, orm):
        "Write your backwards methods here."

         # This migration cannot be reversed
         pass    # don't do anything when running reverse migration
         # or
         raise RuntimeError("Cannot reverse this migration") # stop south from reverting beyond this migration

注意:您无法恢复到以前的列值。如果这不是问题那么这就足够了。

但是,如果您确实希望能够撤消迁移,我建议您创建一个新字段,该字段将保留每行的旧值。

PS:您的迁移文件似乎有误。您不应该为一个应用程序进行两次initial次迁移。在重命名模型(似乎没有重命名)之后,您是否再次运行convert_to_south?最初将现有模型转换为南时,您只需运行convert_to_south一次。之后,您需要创建schema migrations。最简单的方法是使用appname运行schemamigration管理命令,并将--auto作为参数。

python manage.py schemamigration <app_name> --auto

PPS:如果您想重命名模型,请创建一个空迁移并自行编写迁移代码,只需使用db.rename_table即可。如果您在重命名模型后尝试创建自动架构迁移,则IIRC将在创建新表之前删除旧表。

python manage.py schemamigration <app_name> --empty rename_model_x_to_y

并在您的迁移文件中

# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models

class Migration(SchemaMigration):

    def forwards(self, orm):
        "Write your forwards methods here."
        # Note: Don't use "from appname.models import ModelName". 
        # Use orm.ModelName to refer to models in this application,
        # and orm['appname.ModelName'] for models in other applications.
        db.rename_table('old', 'new')

    def backwards(self, orm):
        "Write your backwards methods here."
        db.rename_table('new', 'old')