在Spatialite数据库中使用GeoDjango和South导致“重复列名错误”

2 投票
2 回答
540 浏览
提问于 2025-04-17 16:06

我有一个自定义字段用于 geodjango:

from django.contrib.gis.db import models as geomodels

class PointField(geomodels.PointField):
    def formfield(self, **kwargs):
        defaults = {
            'form_class': CustomFormField
        }
        defaults.update(kwargs)
        return super(PointField, self).formfield(**defaults)


try:
    from south.modelsinspector import add_introspection_rules
    from south.introspection_plugins.geodjango import rules

    add_introspection_rules(rules, ["^project\.apps\.appname\.fields\.PointField"])
except ImportError:
    pass

还有 Django-South 的迁移:

class Migration(SchemaMigration):

    def forwards(self, orm):
        # Adding field 'Address.geoposition'
        db.add_column('company_address', 'geoposition',
                      self.gf('project.apps.appname.fields.PointField')(srid=900913, geography=True),
                      keep_default=False)


    def backwards(self, orm):
        # Deleting field 'Address.geoposition'
        db.delete_column('company_address', 'geoposition')

但是当我执行这个迁移时,我遇到了错误:

AddGeometryColumn() error: "duplicate column name: geoposition"
CreateSpatialIndex() error: either "company_address"."geoposition" isn't a Geometry column or a SpatialIndex is already defined

我已经想尽了办法,不知道该怎么解决这个问题。

软件环境:

  • Django 1.4
  • spatialight 3.0.1
  • gdal 1.9.2
  • South 0.7.6

数据库的地理元数据已经初始化:

subprocess.call(["spatialite", settings.DATABASES['default']['NAME'], "SELECT InitSpatialMetaData();"])

并且添加了 srs 条目:

from django.contrib.gis.utils import add_srs_entry
add_srs_entry(900913)

当我禁用迁移时,没有出现错误。禁用迁移的代码:

SOUTH_MIGRATION_MODULES = {
    'appname': 'ignore',
}

但我希望一切都能正常工作,包括迁移。有没有人知道问题出在哪里?

2 个回答

0

你想要覆盖一个已经存在的模型字段,我觉得你需要对基础类进行一些修改才能实现这个功能。

比如,像下面这样做应该可以解决问题:

from django.contrib.gis.db.models import Address

class CustomPointField(geomodels.PointField):
    def formfield(self, **kwargs):
        defaults = {
            'form_class': CustomFormField
        }
        defaults.update(kwargs)
        return super(PointField, self).formfield(**defaults)

Address.add_to_class('geoposition', CustomPointField())

我不确定 south 是否会识别到这个,所以你可能需要重新同步数据库或者手动进行更改。

2

在查看代码的时候,我发现传统的“修改表”命令在处理空间字段时不太管用,它试图创建一个名为“None”的列,但实际上应该用 AddGeometryColumn 命令来正确创建这个列。不过,South(一个数据库迁移工具)似乎没有意识到这一点,因此 AddGeometryColumn 命令失败了,因为这个列已经存在了。

我还在继续寻找解决办法,但我希望答案只是需要升级到更新的版本。我会及时告诉你们进展的!

Django 源码

撰写回答