2010-03-27 04:14:53 +08:00
===================
GeoDjango Model API
===================
.. module:: django.contrib.gis.db.models
2016-02-19 15:31:25 +08:00
:synopsis: GeoDjango model and field API.
2010-03-27 04:14:53 +08:00
This document explores the details of the GeoDjango Model API. Throughout this
2015-06-19 23:46:03 +08:00
section, we'll be using the following geographic model of a `ZIP code`__ and
of a `Digital Elevation Model`__ as our examples::
2010-03-27 04:14:53 +08:00
from django.contrib.gis.db import models
2010-08-20 03:27:44 +08:00
2010-03-27 04:14:53 +08:00
class Zipcode(models.Model):
code = models.CharField(max_length=5)
poly = models.PolygonField()
2015-06-19 23:46:03 +08:00
class Elevation(models.Model):
name = models.CharField(max_length=100)
rast = models.RasterField()
2015-08-08 18:02:32 +08:00
__ https://en.wikipedia.org/wiki/ZIP_code
2015-06-19 23:46:03 +08:00
__ https://en.wikipedia.org/wiki/Digital_elevation_model
2010-03-27 04:14:53 +08:00
2015-06-19 23:46:03 +08:00
Spatial Field Types
===================
2010-03-27 04:14:53 +08:00
2015-06-19 23:46:03 +08:00
Spatial fields consist of a series of geometry field types and one raster field
type. Each of the geometry field types correspond to the OpenGIS Simple
Features specification [#fnogc]_. There is no such standard for raster data.
2010-03-27 04:14:53 +08:00
``GeometryField``
-----------------
.. class:: GeometryField
2018-08-03 19:54:51 +08:00
The base class for geometry fields.
2010-03-27 04:14:53 +08:00
``PointField``
--------------
.. class:: PointField
2018-08-03 19:54:51 +08:00
Stores a :class:`~django.contrib.gis.geos.Point`.
2010-03-27 04:14:53 +08:00
``LineStringField``
-------------------
.. class:: LineStringField
2018-08-03 19:54:51 +08:00
Stores a :class:`~django.contrib.gis.geos.LineString`.
2010-03-27 04:14:53 +08:00
``PolygonField``
----------------
.. class:: PolygonField
2018-08-03 19:54:51 +08:00
Stores a :class:`~django.contrib.gis.geos.Polygon`.
2010-03-27 04:14:53 +08:00
``MultiPointField``
-------------------
.. class:: MultiPointField
2018-08-03 19:54:51 +08:00
Stores a :class:`~django.contrib.gis.geos.MultiPoint`.
2010-03-27 04:14:53 +08:00
``MultiLineStringField``
------------------------
.. class:: MultiLineStringField
2018-08-03 19:54:51 +08:00
Stores a :class:`~django.contrib.gis.geos.MultiLineString`.
2010-03-27 04:14:53 +08:00
``MultiPolygonField``
---------------------
.. class:: MultiPolygonField
2018-08-03 19:54:51 +08:00
Stores a :class:`~django.contrib.gis.geos.MultiPolygon`.
2010-03-27 04:14:53 +08:00
``GeometryCollectionField``
---------------------------
.. class:: GeometryCollectionField
2018-08-03 19:54:51 +08:00
Stores a :class:`~django.contrib.gis.geos.GeometryCollection`.
2015-06-19 23:46:03 +08:00
``RasterField``
---------------
2010-03-27 04:14:53 +08:00
2015-06-19 23:46:03 +08:00
.. class:: RasterField
2018-08-03 19:54:51 +08:00
Stores a :class:`~django.contrib.gis.gdal.GDALRaster`.
2015-06-19 23:46:03 +08:00
``RasterField`` is currently only implemented for the PostGIS backend.
Spatial Field Options
=====================
2010-03-27 04:14:53 +08:00
In addition to the regular :ref:`common-model-field-options` available for
2015-06-19 23:46:03 +08:00
Django model fields, spatial fields have the following additional options.
2010-03-27 04:14:53 +08:00
All are optional.
``srid``
--------
2015-06-19 23:46:03 +08:00
.. attribute:: BaseSpatialField.srid
2010-03-27 04:14:53 +08:00
Sets the SRID [#fnogcsrid]_ (Spatial Reference System Identity) of the geometry field to
the given value. Defaults to 4326 (also known as `WGS84`__, units are in degrees
of longitude and latitude).
2015-08-08 18:02:32 +08:00
__ https://en.wikipedia.org/wiki/WGS84
2010-03-27 04:14:53 +08:00
.. _selecting-an-srid:
Selecting an SRID
2016-01-03 18:56:22 +08:00
~~~~~~~~~~~~~~~~~
2010-03-27 04:14:53 +08:00
Choosing an appropriate SRID for your model is an important decision that the
2010-08-20 03:27:44 +08:00
developer should consider carefully. The SRID is an integer specifier that
2010-03-27 04:14:53 +08:00
corresponds to the projection system that will be used to interpret the data
in the spatial database. [#fnsrid]_ Projection systems give the context to the
coordinates that specify a location. Although the details of `geodesy`__ are
beyond the scope of this documentation, the general problem is that the earth
2010-10-09 16:12:50 +08:00
is spherical and representations of the earth (e.g., paper maps, Web maps)
2010-03-27 04:14:53 +08:00
are not.
Most people are familiar with using latitude and longitude to reference a
location on the earth's surface. However, latitude and longitude are angles,
2015-08-08 19:56:37 +08:00
not distances. In other words, while the shortest path between two points on
2010-03-27 04:14:53 +08:00
a flat surface is a straight line, the shortest path between two points on a curved
surface (such as the earth) is an *arc* of a `great circle`__. [#fnthematic]_ Thus,
2010-08-20 03:27:44 +08:00
additional computation is required to obtain distances in planar units (e.g.,
2010-03-27 04:14:53 +08:00
kilometers and miles). Using a geographic coordinate system may introduce
2016-08-10 00:46:14 +08:00
complications for the developer later on. For example, SpatiaLite does not have
2014-11-13 21:38:19 +08:00
the capability to perform distance calculations between geometries using
geographic coordinate systems, e.g. constructing a query to find all points
within 5 miles of a county boundary stored as WGS84.
2010-03-31 07:15:43 +08:00
[#fndist]_
2010-03-27 04:14:53 +08:00
2010-08-20 03:27:44 +08:00
Portions of the earth's surface may projected onto a two-dimensional, or
2010-03-27 04:14:53 +08:00
Cartesian, plane. Projected coordinate systems are especially convenient
for region-specific applications, e.g., if you know that your database will
2010-08-20 03:27:44 +08:00
only cover geometries in `North Kansas`__, then you may consider using projection
system specific to that region. Moreover, projected coordinate systems are
defined in Cartesian units (such as meters or feet), easing distance
2010-03-27 04:14:53 +08:00
calculations.
.. note::
2014-02-23 01:30:28 +08:00
If you wish to perform arbitrary distance queries using non-point
2014-11-13 21:38:19 +08:00
geometries in WGS84 in PostGIS and you want decent performance, enable the
:attr:`GeometryField.geography` keyword so that :ref:`geography database
type <geography-type>` is used instead.
2010-03-27 04:14:53 +08:00
Additional Resources:
2010-08-20 03:27:44 +08:00
* `spatialreference.org`__: A Django-powered database of spatial reference
2010-03-27 04:14:53 +08:00
systems.
2015-11-15 20:05:15 +08:00
* `The State Plane Coordinate System`__: A website covering the various
2010-03-27 04:14:53 +08:00
projection systems used in the United States. Much of the U.S. spatial
data encountered will be in one of these coordinate systems rather than
in a geographic coordinate system such as WGS84.
2015-08-08 18:02:32 +08:00
__ https://en.wikipedia.org/wiki/Geodesy
__ https://en.wikipedia.org/wiki/Great_circle
2021-04-27 19:09:00 +08:00
__ https://spatialreference.org/ref/epsg/2796/
2020-01-29 16:34:37 +08:00
__ https://spatialreference.org/
2015-11-30 00:29:46 +08:00
__ https://web.archive.org/web/20080302095452/http://welcome.warnercnr.colostate.edu/class_info/nr502/lg3/datums_coordinates/spcs.html
2010-03-27 04:14:53 +08:00
``spatial_index``
-----------------
2015-06-19 23:46:03 +08:00
.. attribute:: BaseSpatialField.spatial_index
2010-03-27 04:14:53 +08:00
Defaults to ``True``. Creates a spatial index for the given geometry
2010-08-20 03:27:44 +08:00
field.
2010-03-27 04:14:53 +08:00
.. note::
This is different from the ``db_index`` field option because spatial
indexes are created in a different manner than regular database
indexes. Specifically, spatial indexes are typically created using
a variant of the R-Tree, while regular database indexes typically
use B-Trees.
2015-06-19 23:46:03 +08:00
.. _geometry-field-options:
Geometry Field Options
======================
There are additional options available for Geometry fields. All the following
options are optional.
2010-03-27 04:14:53 +08:00
``dim``
-------
.. attribute:: GeometryField.dim
This option may be used for customizing the coordinate dimension of the
geometry field. By default, it is set to 2, for representing two-dimensional
geometries. For spatial backends that support it, it may be set to 3 for
2014-02-15 18:36:53 +08:00
three-dimensional support.
2010-03-27 04:14:53 +08:00
.. note::
2019-11-23 16:59:31 +08:00
At this time 3D support is limited to the PostGIS and SpatiaLite backends.
2010-03-27 04:14:53 +08:00
``geography``
-------------
.. attribute:: GeometryField.geography
2010-03-31 07:15:43 +08:00
If set to ``True``, this option will create a database column of
2010-08-20 03:27:44 +08:00
type geography, rather than geometry. Please refer to the
2010-03-27 04:14:53 +08:00
:ref:`geography type <geography-type>` section below for more
details.
.. note::
2015-03-18 06:34:15 +08:00
Geography support is limited to PostGIS and will force the SRID to be 4326.
2010-03-27 04:14:53 +08:00
.. _geography-type:
Geography Type
2016-01-03 18:56:22 +08:00
~~~~~~~~~~~~~~
2010-03-27 04:14:53 +08:00
2015-03-18 06:34:15 +08:00
The geography type provides native support for spatial features represented
with geographic coordinates (e.g., WGS84 longitude/latitude). [#fngeography]_
2010-03-27 04:14:53 +08:00
Unlike the plane used by a geometry type, the geography type uses a spherical
representation of its data. Distance and measurement operations
performed on a geography column automatically employ great circle arc
calculations and return linear units. In other words, when ``ST_Distance``
is called on two geographies, a value in meters is returned (as opposed
to degrees if called on a geometry column in WGS84).
Because geography calculations involve more mathematics, only a subset of the
PostGIS spatial lookups are available for the geography type. Practically,
this means that in addition to the :ref:`distance lookups <distance-lookups>`
2010-08-20 03:27:44 +08:00
only the following additional :ref:`spatial lookups <spatial-lookups>` are
2010-03-27 04:14:53 +08:00
available for geography columns:
* :lookup:`bboverlaps`
* :lookup:`coveredby`
* :lookup:`covers`
* :lookup:`intersects`
2016-04-11 01:55:29 +08:00
If you need to use a spatial lookup or aggregate that doesn't support the
geography type as input, you can use the
:class:`~django.db.models.functions.Cast` database function to convert the
geography column to a geometry type in the query::
from django.contrib.gis.db.models import PointField
from django.db.models.functions import Cast
Zipcode.objects.annotate(
geom=Cast('geography_field', PointField())
).filter(geom__within=poly)
2010-03-27 04:14:53 +08:00
For more information, the PostGIS documentation contains a helpful section on
determining `when to use geography data type over geometry data type
2017-03-17 02:01:45 +08:00
<https://postgis.net/docs/using_postgis_dbmanagement.html#PostGIS_GeographyVSGeometry>`_.
2010-03-27 04:14:53 +08:00
.. rubric:: Footnotes
2021-04-27 19:09:00 +08:00
.. [#fnogc] OpenGIS Consortium, Inc., `Simple Feature Specification For SQL <https://www.ogc.org/standards/sfs>`_.
2010-03-27 04:14:53 +08:00
.. [#fnogcsrid] *See id.* at Ch. 2.3.8, p. 39 (Geometry Values and Spatial Reference Systems).
2021-04-27 19:09:00 +08:00
.. [#fnsrid] Typically, SRID integer corresponds to an EPSG (`European Petroleum Survey Group <https://epsg.org/>`_) identifier. However, it may also be associated with custom projections defined in spatial database's spatial reference systems table.
2010-03-27 04:14:53 +08:00
.. [#fnthematic] Terry A. Slocum, Robert B. McMaster, Fritz C. Kessler, & Hugh H. Howard, *Thematic Cartography and Geographic Visualization* (Prentice Hall, 2nd edition), at Ch. 7.1.3.
2015-03-18 06:34:15 +08:00
.. [#fndist] This limitation does not apply to PostGIS.
2017-03-17 02:01:45 +08:00
.. [#fngeography] Please refer to the `PostGIS Geography Type <https://postgis.net/docs/using_postgis_dbmanagement.html#PostGIS_Geography>`_ documentation for more details.