【问题标题】:Django south migration - column cannot be cast to type integerDjango南迁移 - 列不能转换为整数类型
【发布时间】:2014-02-11 10:32:25
【问题描述】:
class Stop(models.Model):
    geo_region = models.CharField(max_length=255, default="")

我需要将字段类型更改为此类中的外键,保留数据。所以我做了下面的课程,并做了schemamigrationdatamigration 将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 值与新的外键匹配?

【问题讨论】:

  • 这个:stackoverflow.com/questions/14179063/… 不是一个公认的答案,但应该给你一个想法..
  • 我已经查看了它并将旧数据保存到 GeoRegion 表中。问题是我提到的下一个 DatabaseError 以及如何将值与新的外键匹配。

标签: django django-south


【解决方案1】:

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() 方法。

【讨论】:

  • 我已经将旧数据保存到 GeoRegion 表中。问题是我提到的下一个 DatabaseError 以及如何将值与新的外键匹配。
  • 对。所以问题是当前在stop.geo_region中的Chars
  • 我发布的数据迁移描述了如何将值与新的外键匹配。看看我发布的南文档。您的问题是您的 Stop 表中有 chars 的记录,而 South 不知道如何自行将它们转换为外键。
  • 你是对的,皮特。所以我在问如何解决这个问题。
  • 我发布的南文档以及我的回答都解释了如何解决这个问题。
【解决方案2】:

我通过以下数据迁移解决了这个问题,然后通过模式迁移将字符字段转换为外键。

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

【讨论】:

    猜你喜欢
    • 2016-03-28
    • 2015-09-06
    • 2016-05-23
    • 1970-01-01
    • 2011-04-03
    • 1970-01-01
    • 2020-03-17
    • 2015-11-03
    相关资源
    最近更新 更多