2010-03-27 04:14:53 +08:00
|
|
|
====================================
|
|
|
|
``LayerMapping`` data import utility
|
|
|
|
====================================
|
|
|
|
|
|
|
|
.. module:: django.contrib.gis.utils.layermapping
|
2016-02-19 15:31:25 +08:00
|
|
|
:synopsis: Spatial data import utility for GeoDjango models.
|
2010-03-27 04:14:53 +08:00
|
|
|
|
|
|
|
.. currentmodule:: django.contrib.gis.utils
|
|
|
|
|
|
|
|
The :class:`LayerMapping` class provides a way to map the contents of
|
2011-11-26 16:43:43 +08:00
|
|
|
vector spatial data files (e.g. shapefiles) into GeoDjango models.
|
2010-03-27 04:14:53 +08:00
|
|
|
|
|
|
|
This utility grew out of the author's personal needs to eliminate
|
|
|
|
the code repetition that went into pulling geometries and fields out of
|
2010-08-20 03:27:44 +08:00
|
|
|
a vector layer, converting to another coordinate system (e.g. WGS84), and
|
2010-03-27 04:14:53 +08:00
|
|
|
then inserting into a GeoDjango model.
|
|
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
|
|
Use of :class:`LayerMapping` requires GDAL.
|
|
|
|
|
|
|
|
.. warning ::
|
|
|
|
|
|
|
|
GIS data sources, like shapefiles, may be very large. If you find
|
|
|
|
that :class:`LayerMapping` is using too much memory, set
|
2010-04-10 04:51:01 +08:00
|
|
|
:setting:`DEBUG` to ``False`` in your settings. When :setting:`DEBUG`
|
|
|
|
is set to ``True``, Django :ref:`automatically logs <faq-see-raw-sql-queries>`
|
2019-06-17 22:54:55 +08:00
|
|
|
*every* SQL query -- and when SQL statements contain geometries, this may
|
|
|
|
consume more memory than is typical.
|
2010-03-27 04:14:53 +08:00
|
|
|
|
|
|
|
Example
|
|
|
|
=======
|
|
|
|
|
2018-11-16 02:54:28 +08:00
|
|
|
#. You need a GDAL-supported data source, like a shapefile (here we're using
|
2010-03-27 04:14:53 +08:00
|
|
|
a simple polygon shapefile, ``test_poly.shp``, with three features)::
|
|
|
|
|
|
|
|
>>> from django.contrib.gis.gdal import DataSource
|
|
|
|
>>> ds = DataSource('test_poly.shp')
|
|
|
|
>>> layer = ds[0]
|
2012-04-29 00:02:01 +08:00
|
|
|
>>> print(layer.fields) # Exploring the fields in the layer, we only want the 'str' field.
|
2010-03-27 04:14:53 +08:00
|
|
|
['float', 'int', 'str']
|
2012-04-29 00:02:01 +08:00
|
|
|
>>> print(len(layer)) # getting the number of features in the layer (should be 3)
|
2010-03-27 04:14:53 +08:00
|
|
|
3
|
2012-04-29 00:02:01 +08:00
|
|
|
>>> print(layer.geom_type) # Should be 'Polygon'
|
2010-03-27 04:14:53 +08:00
|
|
|
Polygon
|
2012-04-29 00:02:01 +08:00
|
|
|
>>> print(layer.srs) # WGS84 in WKT
|
2010-03-27 04:14:53 +08:00
|
|
|
GEOGCS["GCS_WGS_1984",
|
|
|
|
DATUM["WGS_1984",
|
|
|
|
SPHEROID["WGS_1984",6378137,298.257223563]],
|
|
|
|
PRIMEM["Greenwich",0],
|
2010-08-20 03:27:44 +08:00
|
|
|
UNIT["Degree",0.017453292519943295]]
|
2010-03-27 04:14:53 +08:00
|
|
|
|
2018-11-16 02:54:28 +08:00
|
|
|
#. Now we define our corresponding Django model (make sure to use :djadmin:`migrate`)::
|
2010-03-27 04:14:53 +08:00
|
|
|
|
|
|
|
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
|
2013-07-04 21:19:33 +08:00
|
|
|
|
2017-01-19 00:51:29 +08:00
|
|
|
def __str__(self):
|
2010-03-27 04:14:53 +08:00
|
|
|
return 'Name: %s' % self.name
|
|
|
|
|
2018-11-16 02:54:28 +08:00
|
|
|
#. Use :class:`LayerMapping` to extract all the features and place them in the
|
2010-03-27 04:14:53 +08:00
|
|
|
database::
|
|
|
|
|
|
|
|
>>> 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
|
2010-08-20 03:27:44 +08:00
|
|
|
>>> lm = LayerMapping(TestGeo, 'test_poly.shp', mapping)
|
|
|
|
>>> lm.save(verbose=True) # Save the layermap, imports the data.
|
2010-03-27 04:14:53 +08:00
|
|
|
Saved: Name: 1
|
|
|
|
Saved: Name: 2
|
|
|
|
Saved: Name: 3
|
|
|
|
|
2019-06-17 22:54:55 +08:00
|
|
|
Here, :class:`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
|
2010-04-10 04:51:01 +08:00
|
|
|
:class:`~django.contrib.gis.gdal.SpatialReference` object to specify one.
|
2010-03-27 04:14:53 +08:00
|
|
|
|
|
|
|
``LayerMapping`` API
|
|
|
|
====================
|
|
|
|
|
2015-07-27 20:35:21 +08:00
|
|
|
.. class:: LayerMapping(model, data_source, mapping, layer=0, source_srs=None, encoding=None, transaction_mode='commit_on_success', transform=True, unique=True, using='default')
|
2010-03-27 04:14:53 +08:00
|
|
|
|
|
|
|
The following are the arguments and keywords that may be used during
|
|
|
|
instantiation of ``LayerMapping`` objects.
|
|
|
|
|
|
|
|
================= =========================================================
|
|
|
|
Argument Description
|
|
|
|
================= =========================================================
|
|
|
|
``model`` The geographic model, *not* an instance.
|
|
|
|
|
|
|
|
``data_source`` The path to the OGR-supported data source file
|
|
|
|
(e.g., a shapefile). Also accepts
|
|
|
|
:class:`django.contrib.gis.gdal.DataSource` instances.
|
|
|
|
|
|
|
|
``mapping`` A dictionary: keys are strings corresponding to
|
|
|
|
the model field, and values correspond to
|
|
|
|
string field names for the OGR feature, or if the
|
|
|
|
model field is a geographic then it should
|
|
|
|
correspond to the OGR geometry type,
|
|
|
|
e.g., ``'POINT'``, ``'LINESTRING'``, ``'POLYGON'``.
|
2010-08-20 03:27:44 +08:00
|
|
|
================= =========================================================
|
2010-03-27 04:14:53 +08:00
|
|
|
|
|
|
|
===================== =====================================================
|
|
|
|
Keyword Arguments
|
2010-08-20 03:27:44 +08:00
|
|
|
===================== =====================================================
|
|
|
|
``layer`` The index of the layer to use from the Data Source
|
2010-03-27 04:14:53 +08:00
|
|
|
(defaults to 0)
|
2010-08-20 03:27:44 +08:00
|
|
|
|
|
|
|
``source_srs`` Use this to specify the source SRS manually (for
|
2014-02-23 01:30:28 +08:00
|
|
|
example, some shapefiles don't come with a ``'.prj'``
|
2010-08-20 03:27:44 +08:00
|
|
|
file). An integer SRID, WKT or PROJ.4 strings, and
|
|
|
|
:class:`django.contrib.gis.gdal.SpatialReference`
|
2010-03-27 04:14:53 +08:00
|
|
|
objects are accepted.
|
2010-08-20 03:27:44 +08:00
|
|
|
|
|
|
|
``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
|
2010-03-27 04:14:53 +08:00
|
|
|
parameters.
|
2010-08-20 03:27:44 +08:00
|
|
|
|
|
|
|
``transaction_mode`` May be ``'commit_on_success'`` (default) or
|
2010-03-27 04:14:53 +08:00
|
|
|
``'autocommit'``.
|
2010-08-20 03:27:44 +08:00
|
|
|
|
|
|
|
``transform`` Setting this to False will disable coordinate
|
2010-03-27 04:14:53 +08:00
|
|
|
transformations. In other words, geometries will
|
|
|
|
be inserted into the database unmodified from their
|
|
|
|
original state in the data source.
|
2010-08-20 03:27:44 +08:00
|
|
|
|
2010-03-27 04:14:53 +08:00
|
|
|
``unique`` Setting this to the name, or a tuple of names,
|
|
|
|
from the given model will create models unique
|
2016-05-12 20:16:18 +08:00
|
|
|
only to the given name(s). Geometries from
|
2010-08-20 03:27:44 +08:00
|
|
|
each feature will be added into the collection
|
|
|
|
associated with the unique model. Forces
|
2010-03-27 04:14:53 +08:00
|
|
|
the transaction mode to be ``'autocommit'``.
|
|
|
|
|
2014-11-16 03:41:25 +08:00
|
|
|
``using`` Sets the database to use when importing spatial data.
|
|
|
|
Default is ``'default'``.
|
2010-08-20 03:27:44 +08:00
|
|
|
===================== =====================================================
|
2010-03-27 04:14:53 +08:00
|
|
|
|
|
|
|
``save()`` Keyword Arguments
|
|
|
|
----------------------------
|
|
|
|
|
2015-07-27 20:35:21 +08:00
|
|
|
.. method:: LayerMapping.save(verbose=False, fid_range=False, step=False, progress=False, silent=False, stream=sys.stdout, strict=False)
|
2010-03-27 04:14:53 +08:00
|
|
|
|
|
|
|
The ``save()`` method also accepts keywords. These keywords are
|
|
|
|
used for controlling output logging, error handling, and for importing
|
|
|
|
specific feature ranges.
|
|
|
|
|
|
|
|
=========================== =================================================
|
|
|
|
Save Keyword Arguments Description
|
|
|
|
=========================== =================================================
|
2010-08-20 03:27:44 +08:00
|
|
|
``fid_range`` May be set with a slice or tuple of
|
|
|
|
(begin, end) feature ID's to map from
|
2010-03-27 04:14:53 +08:00
|
|
|
the data source. In other words, this
|
2010-08-20 03:27:44 +08:00
|
|
|
keyword enables the user to selectively
|
2010-03-27 04:14:53 +08:00
|
|
|
import a subset range of features in the
|
|
|
|
geographic data source.
|
|
|
|
|
|
|
|
``progress`` When this keyword is set, status information
|
2010-08-20 03:27:44 +08:00
|
|
|
will be printed giving the number of features
|
|
|
|
processed and successfully saved. By default,
|
2010-03-27 04:14:53 +08:00
|
|
|
progress information will be printed every 1000
|
2010-08-20 03:27:44 +08:00
|
|
|
features processed, however, this default may
|
|
|
|
be overridden by setting this keyword with an
|
2010-03-27 04:14:53 +08:00
|
|
|
integer for the desired interval.
|
|
|
|
|
2010-08-20 03:27:44 +08:00
|
|
|
``silent`` By default, non-fatal error notifications are
|
|
|
|
printed to ``sys.stdout``, but this keyword may
|
2010-03-27 04:14:53 +08:00
|
|
|
be set to disable these notifications.
|
|
|
|
|
2010-08-20 03:27:44 +08:00
|
|
|
``step`` If set with an integer, transactions will
|
|
|
|
occur at every step interval. For example, if
|
|
|
|
``step=1000``, a commit would occur after the
|
2010-03-27 04:14:53 +08:00
|
|
|
1,000th feature, the 2,000th feature etc.
|
|
|
|
|
|
|
|
|
2010-08-20 03:27:44 +08:00
|
|
|
``stream`` Status information will be written to this file
|
|
|
|
handle. Defaults to using ``sys.stdout``, but
|
2010-03-27 04:14:53 +08:00
|
|
|
any object with a ``write`` method is supported.
|
|
|
|
|
2010-08-20 03:27:44 +08:00
|
|
|
``strict`` Execution of the model mapping will cease upon
|
2010-03-27 04:14:53 +08:00
|
|
|
the first error encountered. The default value
|
|
|
|
(``False``)
|
|
|
|
behavior is to attempt to continue.
|
|
|
|
|
2010-08-20 03:27:44 +08:00
|
|
|
``verbose`` If set, information will be printed
|
|
|
|
subsequent to each model save
|
2010-03-27 04:14:53 +08:00
|
|
|
executed on the database.
|
|
|
|
=========================== =================================================
|
|
|
|
|
|
|
|
Troubleshooting
|
|
|
|
===============
|
|
|
|
|
|
|
|
Running out of memory
|
|
|
|
---------------------
|
|
|
|
|
|
|
|
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`` error
|
|
|
|
-----------------------------------
|
|
|
|
|
|
|
|
If you encounter the following error when using ``LayerMapping`` and 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``
|
2010-08-20 03:27:44 +08:00
|
|
|
setting in your MySQL configuration. For example, the default value may
|
2010-03-27 04:14:53 +08:00
|
|
|
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
|