LayerMapping
数据导入工具¶
LayerMapping
类提供了一种将矢量空间数据文件(例如 shapefile)的内容映射到 GeoDjango 模型中的方法。
此工具源于作者的个人需求,即消除从矢量图层中提取几何图形和字段、转换为另一个坐标系(例如 WGS84)以及随后插入到 GeoDjango 模型中所需的代码重复。
注意
使用 LayerMapping
需要 GDAL。
警告
GIS 数据源(如 shapefile)可能非常大。如果您发现 LayerMapping
使用了太多内存,请在设置中将 DEBUG
设置为 False
。当 DEBUG
设置为 True
时,Django 会 自动记录 每个 SQL 查询 - 当 SQL 语句包含几何图形时,这可能会消耗比平常更多的内存。
示例¶
- 您需要一个 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]]
现在我们定义相应的 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
使用
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