Django南迁移 - 列不能转换为整数类型

时间:2014-01-21 17:14:26

标签: django django-south

class Stop(models.Model):
    geo_region = models.CharField(max_length=255, default="")

我需要在此类中将字段类型更改为外键,以保留数据。所以我创建了下面的类并进行了schemamigration和datamigration以将geo_name值保存到新表中。

class GeoRegion(models.Model):
    geo_name = models.CharField(max_length=255, unique=True, verbose_name=u'Name')

    def __unicode__(self):
        return u"%s" % self.name

我改变了geo_region的字段类型。

class Stop(models.Model):
    geo_region = models.ForeignKey(GeoRegion)

然后我再次运行south schemamigration命令并出错;

DatabaseError: column "geo_region_id" cannot be cast to type integer

如何解决此问题并将现有geo_name值与新外键匹配?

2 个答案:

答案 0 :(得分:1)

我通过以下数据迁移解决了这个问题,然后使用schemamigration将charfield转换为foreignkey。

class Migration(DataMigration):

def forwards(self, orm):
    for region in orm['runs.Stop'].objects.distinct('geo_region'):
        orm['runs.GeoRegion'].objects.create(geo_name=region.geo_region)
    db.start_transaction()
    db.add_column('runs_stop', 'geo_region_tmp', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
    db.commit_transaction()
    db.start_transaction()
    db.execute('Update runs_stop AS R SET geo_region_tmp=s.id FROM runs_georegion S WHERE S.geo_name=R.geo_region')
    db.delete_column('runs_stop', 'geo_region')
    db.add_column('runs_stop', 'geo_region', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
    db.commit_transaction()
    db.start_transaction()
    db.execute('Update runs_stop SET geo_region=geo_region_tmp')
    db.delete_column('runs_stop', 'geo_region_tmp')
    db.commit_transaction()

答案 1 :(得分:0)

Stop字段下的geo_region数据库表中有旧数据。 South正在获取该数据并尝试将其放入新的models.ForeignKey()字段(期望geo_region模型的实例)。您需要编写一个数据迁移(例如,参见South documentation),它可以删除旧数据或转换它,例如:

def forwards(self, orm):
    for stop in orm.Stop.objects.all():
        geo_region = GeoRegion.objects.get(geo_name=stop.geo_region)
        stop.geo_region = geo_region
        stop.save()

未经测试的代码,但应该类似。您可能还想编写backwards()方法。