# Django 5.2.8 documentation

# `LayerMapping` 是一个数据导入实用程序

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

这个实用程序是为了消除重复的代码，用于从矢量图层中提取几何和字段，将其转换为另一个坐标系统（例如 WGS84），然后插入到 GeoDjango 模型中而产生的。

Note

使用 `LayerMapping` 需要 GDAL。

Warning

GIS data sources, like shapefiles, may be very large. If you find that `LayerMapping` is using too much memory, set `DEBUG` to `False` in your settings. When `DEBUG` is set to `True`, Django automatically logs every SQL query -- and when SQL statements contain geometries, this may consume more memory than is typical.

## 例如

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

Here, `LayerMapping` transformed the three geometries from the shapefile in their original spatial reference system (WGS84) to the spatial reference system of the GeoDjango model (NAD83). If no spatial reference system is defined for the layer, use the `source_srs` keyword with a `SpatialReference` object to specify one.

## `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` | The path to the OGR-supported data source file (e.g., a shapefile). Also accepts `django.contrib.gis.gdal.DataSource` instances.
`mapping` | 一个字典：键是与模型字段对应的字符串，值对应于 OGR 要素的字符串字段名称，或者如果模型字段是地理字段，则应该对应于 OGR 几何类型，例如 `'POINT'`、`'LINESTRING'`、`'POLYGON'`。

关键字参数 |
--- | ---
`layer` | 要使用的数据源中的图层的索引（默认为0）。
`source_srs` | Use this to specify the source SRS manually (for example, some shapefiles don't come with a `'.prj'` file). An integer SRID, WKT or PROJ strings, and `django.contrib.gis.gdal.SpatialReference` objects are accepted.
`encoding` | Specifies the character set encoding of the strings in the OGR data source. For example, `'latin-1'`, `'utf-8'`, and `'cp437'` are all valid encoding parameters.
`transaction_mode` | 可以是 `'commit_on_success'` （默认）或 `'autocommit'`。
`transform` | Setting this to False will disable coordinate transformations. In other words, geometries will be inserted into the database unmodified from their original state in the data source.
`unique` | Setting this to the name, or a tuple of names, from the given model will create models unique only to the given name(s). Geometries from each feature will be added into the collection associated with the unique model. Forces the transaction mode to be `'autocommit'`.
`using` | 在导入空间数据时设置要使用的数据库。默认为 `'default'`。

### `save()` 关键字参数

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

The `save()` method also accepts keywords. These keywords are used for controlling output logging, error handling, and for importing specific feature ranges.

保存关键字参数 | 描述
--- | ---
`fid_range` | May be set with a slice or tuple of (begin, end) feature ID's to map from the data source. In other words, this keyword enables the user to selectively import a subset range of features in the geographic data source.
`progress` | When this keyword is set, status information will be printed giving the number of features processed and successfully saved. By default, progress information will be printed every 1000 features processed, however, this default may be overridden by setting this keyword with an integer for the desired interval.
`silent` | 默认情况下，非致命错误通知将打印到 `sys.stdout`，但可以通过设置这个关键字来禁用这些通知。
`step` | 如果设置为整数，事务将在每个步骤间隔之后发生。例如，如果 `step=1000`，则在第 1000 个要素、第 2000 个要素等之后会发生提交。
`stream` | Status information will be written to this file handle. Defaults to using `sys.stdout`, but any object with a `write` method is supported.
`strict` | Execution of the model mapping will cease upon the first error encountered. The default value (`False`) behavior is to attempt to continue.
`verbose` | 如果设置，将在执行数据库上的每个模型保存后打印信息。

## 错误调试

### 内存耗尽

As noted in the warning at the top of this section, Django stores all SQL queries when `DEBUG=True`. Set `DEBUG=False` in your settings, and this should stop excessive memory use when running `LayerMapping` scripts.

### MySQL: `max_allowed_packet` 错误

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

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

Then the solution is to increase the value of the `max_allowed_packet` setting in your MySQL configuration. For example, the default value may be something low like one megabyte -- the setting may be modified in MySQL's configuration file (`my.cnf`) in the `[mysqld]` section:

    max_allowed_packet = 10M