LayerMapping 数据导入工具

LayerMapping 类提供了一种将矢量空间数据文件(例如 shapefile)的内容映射到 GeoDjango 模型中的方法。

此工具源于作者的个人需求,即消除从矢量图层中提取几何图形和字段、转换为另一个坐标系(例如 WGS84)以及随后插入到 GeoDjango 模型中所需的代码重复。

注意

使用 LayerMapping 需要 GDAL。

警告

GIS 数据源(如 shapefile)可能非常大。如果您发现 LayerMapping 使用了太多内存,请在设置中将 DEBUG 设置为 False。当 DEBUG 设置为 True 时,Django 会 自动记录 每个 SQL 查询 - 当 SQL 语句包含几何图形时,这可能会消耗比平常更多的内存。

示例

  1. 您需要一个 GDAL 支持的数据源,例如 shapefile(这里我们使用一个简单的多边形 shapefile,test_poly.shp,具有三个要素)
>>> from django.contrib.gis.gdal import DataSource
>>> ds = DataSource("test_poly.shp")
>>> layer = ds[0]
>>> print(layer.fields)  # Exploring the fields in the layer, we only want the 'str' field.
['float', 'int', 'str']
>>> print(len(layer))  # getting the number of features in the layer (should be 3)
3
>>> print(layer.geom_type)  # Should be 'Polygon'
Polygon
>>> print(layer.srs)  # WGS84 in WKT
GEOGCS["GCS_WGS_1984",
    DATUM["WGS_1984",
        SPHEROID["WGS_1984",6378137,298.257223563]],
    PRIMEM["Greenwich",0],
    UNIT["Degree",0.017453292519943295]]
  1. 现在我们定义相应的 Django 模型(确保使用 migrate

    from django.contrib.gis.db import models
    
    
    class TestGeo(models.Model):
        name = models.CharField(max_length=25)  # corresponds to the 'str' field
        poly = models.PolygonField(srid=4269)  # we want our model in a different SRID
    
        def __str__(self):
            return "Name: %s" % self.name
    
  2. 使用 LayerMapping 提取所有要素并将它们放入数据库中

>>> from django.contrib.gis.utils import LayerMapping
>>> from geoapp.models import TestGeo
>>> mapping = {
...     "name": "str",  # The 'name' model field maps to the 'str' layer field.
...     "poly": "POLYGON",  # For geometry fields use OGC name.
... }  # The mapping is a dictionary
>>> lm = LayerMapping(TestGeo, "test_poly.shp", mapping)
>>> lm.save(verbose=True)  # Save the layermap, imports the data.
Saved: Name: 1
Saved: Name: 2
Saved: Name: 3

在这里,LayerMapping 将 shapefile 中的三个几何图形从其原始空间参考系 (WGS84) 转换为了 GeoDjango 模型的空间参考系 (NAD83)。如果未为图层定义空间参考系,请使用带有 SpatialReference 对象的 source_srs 关键字来指定一个。

LayerMapping API

class LayerMapping(model, data_source, mapping, layer=0, source_srs=None, encoding=None, transaction_mode='commit_on_success', transform=True, unique=True, using='default')

以下是实例化 LayerMapping 对象期间可以使用的参数和关键字。

参数 描述
model 地理模型,不是 实例。
data_source OGR 支持的数据源文件的路径(例如,shapefile)。也接受 django.contrib.gis.gdal.DataSource 实例。
mapping 字典:键是与模型字段对应的字符串,值是 OGR 要素的字符串字段名称,或者如果模型字段是地理字段,则它应该对应于 OGR 几何类型,例如,'POINT''LINESTRING''POLYGON'
关键字参数  
layer 要从数据源使用的图层的索引(默认为 0)
source_srs 使用此选项手动指定源 SRS(例如,某些 shapefile 没有 '.prj' 文件)。接受整数 SRID、WKT 或 PROJ 字符串以及 django.contrib.gis.gdal.SpatialReference 对象。
encoding 指定 OGR 数据源中字符串的字符集编码。例如,'latin-1''utf-8''cp437' 都是有效的编码参数。
transaction_mode 可以是 'commit_on_success'(默认)或 'autocommit'
transform 将其设置为 False 将禁用坐标转换。换句话说,几何图形将按其在数据源中的原始状态插入数据库,不做修改。
unique 将此设置为给定模型中的名称或名称元组,将创建仅对给定名称唯一的模型。每个要素的几何图形将被添加到与唯一模型关联的集合中。强制事务模式为 'autocommit'
using 设置导入空间数据时要使用的数据库。默认为 'default'

save() 关键字参数

LayerMapping.save(verbose=False, fid_range=False, step=False, progress=False, silent=False, stream=sys.stdout, strict=False)

save() 方法也接受关键字。这些关键字用于控制输出日志记录、错误处理以及导入特定的要素范围。

保存关键字参数 描述
fid_range 可以使用切片或元组 (begin, end) 要素 ID 来设置,以从数据源映射。换句话说,此关键字使用户能够选择性地导入地理数据源中的子集范围。
progress 设置此关键字后,将打印状态信息,给出已处理和成功保存的要素数量。默认情况下,每处理 1000 个要素将打印一次进度信息,但是,可以通过使用所需间隔的整数设置此关键字来覆盖此默认值。
silent 默认情况下,非致命错误通知会打印到 sys.stdout,但可以设置此关键字以禁用这些通知。
step 如果设置为整数,则每隔 step 间隔就会发生一次事务。例如,如果 step=1000,则在第 1,000 个要素、第 2,000 个要素等之后会发生一次提交。
stream 状态信息将写入此文件句柄。默认为使用 sys.stdout,但支持任何具有 write 方法的对象。
strict 模型映射的执行将在遇到第一个错误时停止。默认值 (False) 行为是尝试继续。
verbose 如果设置,则在对数据库执行每个模型保存后,将打印信息。

故障排除

内存不足

如本节顶部的警告中所述,Django 在 DEBUG=True 时存储所有 SQL 查询。在您的设置中设置 DEBUG=False,这应该会在运行 LayerMapping 脚本时停止过度使用内存。

MySQL:max_allowed_packet 错误

如果在使用 LayerMapping 和 MySQL 时遇到以下错误

OperationalError: (1153, "Got a packet bigger than 'max_allowed_packet' bytes")

那么解决方案是增加 MySQL 配置中 max_allowed_packet 设置的值。例如,默认值可能很低,例如 1 兆字节 - 可以在 MySQL 的配置文件 (my.cnf) 的 [mysqld] 部分中修改该设置

max_allowed_packet = 10M
返回顶部