문제

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

I need to change the field type to a foreign key in this class, keeping the data. So I made the below class and did the schemamigration and datamigration to save the geo_name values into the new table.

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

And I changed the field type of the geo_region.

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

Then I run the south schemamigration command again and got an error;

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

How can I resolve this issue out and match the existing geo_name values to the new foreign key?

도움이 되었습니까?

해결책

I resolved this issue by the below datamigration and then schemamigration to convert the charfield to 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()

다른 팁

You have old data in your Stop database table under the geo_region field. South is taking that data and trying to put it into the new models.ForeignKey() field (which is expecting an instance of the geo_region model). You need to write a data migration (see, for example, the South documentation) that either gets rid of the old data, or converts it, something like:

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()

untested code, but it should be similar. You might also want to write a backwards() method.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top