3
====================================
4
``LayerMapping`` data import utility
5
====================================
7
.. module:: django.contrib.gis.utils.layermapping
8
:synopsis: Spatial data import utility for GeoDjango models.
10
.. currentmodule:: django.contrib.gis.utils
12
The :class:`LayerMapping` class provides a way to map the contents of
13
vector spatial data files (e.g. shapefiles) intoto GeoDjango models.
15
This utility grew out of the author's personal needs to eliminate
16
the code repetition that went into pulling geometries and fields out of
17
a vector layer, converting to another coordinate system (e.g. WGS84), and
18
then inserting into a GeoDjango model.
22
Use of :class:`LayerMapping` requires GDAL.
26
GIS data sources, like shapefiles, may be very large. If you find
27
that :class:`LayerMapping` is using too much memory, set
28
:setting:`DEBUG` to ``False`` in your settings. When :setting:`DEBUG`
29
is set to ``True``, Django :ref:`automatically logs <faq-see-raw-sql-queries>`
30
*every* SQL query -- thus, when SQL statements contain geometries, it is
31
easy to consume more memory than is typical.
36
1. You need a GDAL-supported data source, like a shapefile (here we're using
37
a simple polygon shapefile, ``test_poly.shp``, with three features)::
39
>>> from django.contrib.gis.gdal import DataSource
40
>>> ds = DataSource('test_poly.shp')
42
>>> print layer.fields # Exploring the fields in the layer, we only want the 'str' field.
43
['float', 'int', 'str']
44
>>> print len(layer) # getting the number of features in the layer (should be 3)
46
>>> print layer.geom_type # Should be 'Polygon'
48
>>> print layer.srs # WGS84 in WKT
49
GEOGCS["GCS_WGS_1984",
51
SPHEROID["WGS_1984",6378137,298.257223563]],
52
PRIMEM["Greenwich",0],
53
UNIT["Degree",0.017453292519943295]]
55
2. Now we define our corresponding Django model (make sure to use ``syncdb``)::
57
from django.contrib.gis.db import models
59
class TestGeo(models.Model):
60
name = models.CharField(max_length=25) # corresponds to the 'str' field
61
poly = models.PolygonField(srid=4269) # we want our model in a different SRID
62
objects = models.GeoManager()
63
def __unicode__(self):
64
return 'Name: %s' % self.name
66
3. Use :class:`LayerMapping` to extract all the features and place them in the
69
>>> from django.contrib.gis.utils import LayerMapping
70
>>> from geoapp.models import TestGeo
71
>>> mapping = {'name' : 'str', # The 'name' model field maps to the 'str' layer field.
72
'poly' : 'POLYGON', # For geometry fields use OGC name.
73
} # The mapping is a dictionary
74
>>> lm = LayerMapping(TestGeo, 'test_poly.shp', mapping)
75
>>> lm.save(verbose=True) # Save the layermap, imports the data.
80
Here, :class:`LayerMapping` just transformed the three geometries from the
81
shapefile in their original spatial reference system (WGS84) to the spatial
82
reference system of the GeoDjango model (NAD83). If no spatial reference
83
system is defined for the layer, use the ``source_srs`` keyword with a
84
:class:`~django.contrib.gis.gdal.SpatialReference` object to specify one.
89
.. class:: LayerMapping(model, data_source, mapping[, layer=0, source_srs=None, encoding=None, transaction_mode='commit_on_success', transform=True, unique=True, using='default'])
91
The following are the arguments and keywords that may be used during
92
instantiation of ``LayerMapping`` objects.
94
================= =========================================================
96
================= =========================================================
97
``model`` The geographic model, *not* an instance.
99
``data_source`` The path to the OGR-supported data source file
100
(e.g., a shapefile). Also accepts
101
:class:`django.contrib.gis.gdal.DataSource` instances.
103
``mapping`` A dictionary: keys are strings corresponding to
104
the model field, and values correspond to
105
string field names for the OGR feature, or if the
106
model field is a geographic then it should
107
correspond to the OGR geometry type,
108
e.g., ``'POINT'``, ``'LINESTRING'``, ``'POLYGON'``.
109
================= =========================================================
111
===================== =====================================================
113
===================== =====================================================
114
``layer`` The index of the layer to use from the Data Source
117
``source_srs`` Use this to specify the source SRS manually (for
118
example, some shapefiles don't come with a '.prj'
119
file). An integer SRID, WKT or PROJ.4 strings, and
120
:class:`django.contrib.gis.gdal.SpatialReference`
121
objects are accepted.
123
``encoding`` Specifies the character set encoding of the strings
124
in the OGR data source. For example, ``'latin-1'``,
125
``'utf-8'``, and ``'cp437'`` are all valid encoding
128
``transaction_mode`` May be ``'commit_on_success'`` (default) or
131
``transform`` Setting this to False will disable coordinate
132
transformations. In other words, geometries will
133
be inserted into the database unmodified from their
134
original state in the data source.
136
``unique`` Setting this to the name, or a tuple of names,
137
from the given model will create models unique
138
only to the given name(s). Geometries will from
139
each feature will be added into the collection
140
associated with the unique model. Forces
141
the transaction mode to be ``'autocommit'``.
143
``using`` New in version 1.2. Sets the database to use when
144
importing spatial data. Default is ``'default'``
145
===================== =====================================================
147
``save()`` Keyword Arguments
148
----------------------------
150
.. method:: LayerMapping.save([verbose=False, fid_range=False, step=False, progress=False, silent=False, stream=sys.stdout, strict=False])
152
The ``save()`` method also accepts keywords. These keywords are
153
used for controlling output logging, error handling, and for importing
154
specific feature ranges.
156
=========================== =================================================
157
Save Keyword Arguments Description
158
=========================== =================================================
159
``fid_range`` May be set with a slice or tuple of
160
(begin, end) feature ID's to map from
161
the data source. In other words, this
162
keyword enables the user to selectively
163
import a subset range of features in the
164
geographic data source.
166
``progress`` When this keyword is set, status information
167
will be printed giving the number of features
168
processed and successfully saved. By default,
169
progress information will be printed every 1000
170
features processed, however, this default may
171
be overridden by setting this keyword with an
172
integer for the desired interval.
174
``silent`` By default, non-fatal error notifications are
175
printed to ``sys.stdout``, but this keyword may
176
be set to disable these notifications.
178
``step`` If set with an integer, transactions will
179
occur at every step interval. For example, if
180
``step=1000``, a commit would occur after the
181
1,000th feature, the 2,000th feature etc.
184
``stream`` Status information will be written to this file
185
handle. Defaults to using ``sys.stdout``, but
186
any object with a ``write`` method is supported.
188
``strict`` Execution of the model mapping will cease upon
189
the first error encountered. The default value
191
behavior is to attempt to continue.
193
``verbose`` If set, information will be printed
194
subsequent to each model save
195
executed on the database.
196
=========================== =================================================
201
Running out of memory
202
---------------------
204
As noted in the warning at the top of this section, Django stores all SQL
205
queries when ``DEBUG=True``. Set ``DEBUG=False`` in your settings, and this
206
should stop excessive memory use when running ``LayerMapping`` scripts.
208
MySQL: ``max_allowed_packet`` error
209
-----------------------------------
211
If you encounter the following error when using ``LayerMapping`` and MySQL::
213
OperationalError: (1153, "Got a packet bigger than 'max_allowed_packet' bytes")
215
Then the solution is to increase the value of the ``max_allowed_packet``
216
setting in your MySQL configuration. For example, the default value may
217
be something low like one megabyte -- the setting may be modified in MySQL's
218
configuration file (``my.cnf``) in the ``[mysqld]`` section::
220
max_allowed_packet = 10M