LayerMapping 数据导入工具 — Django 文档

来自菜鸟教程
Django/docs/3.1.x/ref/contrib/gis/layermapping
跳转至:导航、​搜索

LayerMapping 数据导入实用程序

LayerMapping 类提供了一种映射矢量空间数据文件(例如 shapefiles) 到 GeoDjango 模型中。

该实用程序源于作者的个人需要,以消除将几何图形和场从矢量图层中提取出来的代码重复,转换为另一个坐标系(例如 WGS84),然后插入到 GeoDjango 模型中。

笔记

使用 LayerMapping 需要 GDAL。


警告

GIS 数据源(如 shapefile)可能非常大。 如果您发现 LayerMapping 使用过多内存,请在您的设置中将 :setting:`DEBUG` 设置为 False。 当 :setting:`DEBUG` 设置为 True 时,Django 自动记录 every 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]]
  2. 现在我们定义我们对应的 Django 模型(确保使用 :djadmin:`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
  3. 使用 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 将三个几何图形从原始空间参考系统 (WGS84) 中的 shapefile 转换为 GeoDjango 模型 (NAD83) 的空间参考系统。 如果没有为图层定义空间参考系统,请使用 source_srs 关键字和 SpatialReference 对象来指定一个。


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.4 字符串和 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 可以设置一个切片或元组(开始,结束)要从数据源映射的特征 ID。 换言之,该关键字使用户能够有选择地导入地理数据源中的要素子集范围。
progress 设置此关键字后,将打印状态信息,提供已处理和成功保存的功能数量。 默认情况下,每处理 1000 个特征就会打印一次进度信息,但是,可以通过将此关键字设置为所需间隔的整数来覆盖此默认值。
silent 默认情况下,非致命错误通知会打印到 sys.stdout,但可以设置此关键字以禁用这些通知。
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