在GeoDjango中导入空间数据时出错 - 对于mpoly字段的KeyError

Roh*_*ain 7 python django geodjango python-2.7

我正在关注https://docs.djangoproject.com/en/1.8/ref/contrib/gis/tutorial/#importing-spatial-data上的教程,以便在我的机器上设置GeoDjango.但似乎那里存在一些问题.通过运行使用LayerMapping导入数据时load.run(),我收到以下错误:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/ubuntu/src/django/world/load.py", line 23, in run
    lm = LayerMapping(WorldBorder, world_shp, world_mapping, transform=False, encoding='iso-8859-1')
  File "/home/ubuntu/Envs/vir-env/local/lib/python2.7/site-packages/django/contrib/gis/utils/layermapping.py", line 105, in __init__
    self.check_layer()
  File "/home/ubuntu/Envs/vir-env/local/lib/python2.7/site-packages/django/contrib/gis/utils/layermapping.py", line 178, in check_layer
    ogr_field_types = self.layer.field_types
  File "/home/ubuntu/Envs/vir-env/local/lib/python2.7/site-packages/django/contrib/gis/gdal/layer.py", line 153, in field_types
    for i in range(self.num_fields)]
KeyError: 12
Run Code Online (Sandbox Code Playgroud)

然后我发现.shp文件中没有'MULTIPOLYGON'字段:

>>> from django.contrib.gis.gdal import DataSource
>>> ds = DataSource('world/data/TM_WORLD_BORDERS-0.3.shp')
>>> layer = ds[0]
>>> layer.fields
[u'FIPS', u'ISO2', u'ISO3', u'UN', u'NAME', u'AREA', u'POP2005', u'REGION', u'SUBREGION', u'LON', u'LAT']
Run Code Online (Sandbox Code Playgroud)

但它在WorldBorder模型中就是类型MultiPolygonField.因此,绝对在world_mapping文件中,导入将失败以进行'mpoly': 'MULTIPOLYGON'映射.还有其他人遇到过这个问题吗?我希望如此,因为我一步一步地按照教程.但它没有说明这个问题.如果我通过删除mpoly映射加载数据会有什么影响?

这是我的load.py文件:

  1 import os
  2 from django.contrib.gis.utils import LayerMapping
  3 from models import WorldBorder
  4
  5 world_mapping = {
  6     'fips' : 'FIPS',
  7     'iso2' : 'ISO2',
  8     'iso3' : 'ISO3',
  9     'un' : 'UN',
 10     'name' : 'NAME',
 11     'area' : 'AREA',
 12     'pop2005' : 'POP2005',
 13     'region' : 'REGION',
 14     'subregion' : 'SUBREGION',
 15     'lon' : 'LON',
 16     'lat' : 'LAT',
 17     'mpoly' : 'MULTIPOLYGON',
 18 }
 19
 20 world_shp = os.path.abspath(os.path.join(os.path.dirname(__file__), 'data/TM_WORLD_BORDERS-0.3.shp'))
 21
 22 def run(verbose=True):
 23     lm = LayerMapping(WorldBorder, world_shp, world_mapping, transform=False, encoding='iso-8859-1')
 24
 25     lm.save(strict=True, verbose=verbose)
Run Code Online (Sandbox Code Playgroud)

只是一个更新:经过源代码,通过堆栈跟踪,我发现我无法访问模块的field_types属性layer.所以,从python shell,当我访问该属性时,我得到相同的错误:

>>> from django.contrib.gis.gdal import DataSource
>>> ds = DataSource(wshp)
>>> layer = ds[0]
>>> layer.fields
[u'FIPS', u'ISO2', u'ISO3', u'UN', u'NAME', u'AREA', u'POP2005', u'REGION', u'SUBREGION', u'LON', u'LAT']
>>> layer.field_types
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/ubuntu/Envs/rj-venv/local/lib/python2.7/site-packages/django/contrib/gis/gdal/layer.py", line 153, in field_types
    for i in range(self.num_fields)]
KeyError: 12
Run Code Online (Sandbox Code Playgroud)

现在,这很奇怪,因为现在我也mpolyWorldBorder模型中删除了字段.


更新2:

在深入了解源代码后,我发现OGDFieldTypes在我的gdal版本中,可能没有密钥12,如源代码所示:https://github.com/django/django/blob/master/django/ contrib/gis/gdal/field.py.但是它说键12和13将可用GDAL 2,这就是我安装的.现在真的似乎是图书馆之间的一些冲突.

我安装了以下库:

  • GEOS-3.4.2.tar.bz2
  • PROJ-datumgrid-1.5.tar.gz
  • PROJ-4.8.0.tar.gz
  • @中-2.0.0.tar.gz

PostGIS版本2.1.5安装在Amazon RDS实例中.

J R*_*ape 7

这里的问题是Django的1.8.2版本(编写本文时的最新版本)不支持GDAL 2.0.0字段类型.对此的修复是在Django主代码分支中 - 但尚未在发行版中.

在编写本文时,您有两个选项 - 从Github上的最新源构建Django(即升级),或降级GDAL,以便此行调用的本机代码不能将值12作为字段类型返回.

因为GDAL 2.0 可以12作为字段类型返回,所以查看到这个字典会失败,KeyError你会看到使用Django 1.8.2代码. 在master上,它dict包含GDAL 2.0的正确字段 - 由此提交修复(在编写时仅9天!).


为了完整性 - 在SOPython聊天室中讨论了这个故障的诊断 - 这里有书签对话的链接

来自聊天的NB如果您安装了多个GDAL版本,则可能必须添加GDAL_LIBRARY_PATHdjango设置文件以指向正确的版本libgdal.so(或者我猜相应的,.dll如果您在Windows上)