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