Vous êtes sur la page 1sur 6

..

_ref-gis-db-api:
======================
GeoDjango Database API
======================
.. _spatial-backends:
Spatial Backends
================
.. module:: django.contrib.gis.db.backends
:synopsis: GeoDjango's spatial database backends.
GeoDjango currently provides the following spatial database backends:
*
*
*
*

``django.contrib.gis.db.backends.postgis``
``django.contrib.gis.db.backends.mysql``
``django.contrib.gis.db.backends.oracle``
``django.contrib.gis.db.backends.spatialite``

.. module:: django.contrib.gis.db.models
:synopsis: GeoDjango's database API.
.. _mysql-spatial-limitations:
MySQL Spatial Limitations
------------------------MySQL's spatial extensions only support bounding box operations
(what MySQL calls minimum bounding rectangles, or MBR). Specifically,
`MySQL does not conform to the OGC standard <http://dev.mysql.com/doc/refman/5.1
/en/functions-for-testing-spatial-relations-between-geometric-objects.html>`_:
Currently, MySQL does not implement these functions
[``Contains``, ``Crosses``, ``Disjoint``, ``Intersects``, ``Overlaps``,
``Touches``, ``Within``]
according to the specification. Those that are implemented return
the same result as the corresponding MBR-based functions.
In other words, while spatial lookups such as :lookup:`contains <gis-contains>`
are available in GeoDjango when using MySQL, the results returned are really
equivalent to what would be returned when using :lookup:`bbcontains`
on a different spatial backend.
.. warning::
True spatial indexes (R-trees) are only supported with
MyISAM tables on MySQL. [#fnmysqlidx]_ In other words, when using
MySQL spatial extensions you have to choose between fast spatial
lookups and the integrity of your data -- MyISAM tables do
not support transactions or foreign key constraints.
Creating and Saving Geographic Models
=====================================
Here is an example of how to create a geometry object (assuming the ``Zipcode``
model)::
>>> from zipcode.models import Zipcode
>>> z = Zipcode(code=77096, poly='POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 1

0))')
>>> z.save()
:class:`~django.contrib.gis.geos.GEOSGeometry` objects may also be used to save
geometric models::
>>>
>>>
>>>
>>>

from django.contrib.gis.geos import GEOSGeometry


poly = GEOSGeometry('POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))')
z = Zipcode(code=77096, poly=poly)
z.save()

Moreover, if the ``GEOSGeometry`` is in a different coordinate system (has a


different SRID value) than that of the field, then it will be implicitly
transformed into the SRID of the model's field, using the spatial database's
transform procedure::
>>> poly_3084 = GEOSGeometry('POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))'
, srid=3084) # SRID 3084 is 'NAD83(HARN) / Texas Centric Lambert Conformal'
>>> z = Zipcode(code=78212, poly=poly_3084)
>>> z.save()
>>> from django.db import connection
>>> print(connection.queries[-1]['sql']) # printing the last SQL statement e
xecuted (requires DEBUG=True)
INSERT INTO "geoapp_zipcode" ("code", "poly") VALUES (78212, ST_Transform(ST
_GeomFromWKB('\\001 ... ', 3084), 4326))
Thus, geometry parameters may be passed in using the ``GEOSGeometry`` object, WK
T
(Well Known Text [#fnwkt]_), HEXEWKB (PostGIS specific -- a WKB geometry in
hexadecimal [#fnewkb]_), and GeoJSON [#fngeojson]_ (requires GDAL). Essentially,
if the input is not a ``GEOSGeometry`` object, the geometry field will attempt t
o
create a ``GEOSGeometry`` instance from the input.
For more information creating :class:`~django.contrib.gis.geos.GEOSGeometry`
objects, refer to the :ref:`GEOS tutorial <geos-tutorial>`.
.. _spatial-lookups-intro:
Spatial Lookups
===============
GeoDjango's lookup types may be used with any manager method like
``filter()``, ``exclude()``, etc. However, the lookup types unique to
GeoDjango are only available on geometry fields.
Filters on 'normal' fields (e.g. :class:`~django.db.models.CharField`)
may be chained with those on geographic fields. Thus, geographic queries
take the following general form (assuming the ``Zipcode`` model used in the
:ref:`ref-gis-model-api`)::
>>> qs = Zipcode.objects.filter(<field>__<lookup_type>=<parameter>)
>>> qs = Zipcode.objects.exclude(...)
For example::
>>> qs = Zipcode.objects.filter(poly__contains=pnt)
In this case, ``poly`` is the geographic field, :lookup:`contains <gis-contains>
`
is the spatial lookup type, and ``pnt`` is the parameter (which may be a

:class:`~django.contrib.gis.geos.GEOSGeometry` object or a string of


GeoJSON , WKT, or HEXEWKB).
A complete reference can be found in the :ref:`spatial lookup reference
<spatial-lookups>`.
.. note::
GeoDjango constructs spatial SQL with the :class:`GeoQuerySet`, a
subclass of :class:`~django.db.models.query.QuerySet`. The
:class:`GeoManager` instance attached to your model is what
enables use of :class:`GeoQuerySet`.
.. _distance-queries:
Distance Queries
================
Introduction
-----------Distance calculations with spatial data is tricky because, unfortunately,
the Earth is not flat. Some distance queries with fields in a geographic
coordinate system may have to be expressed differently because of
limitations in PostGIS. Please see the :ref:`selecting-an-srid` section
in the :ref:`ref-gis-model-api` documentation for more details.
.. _distance-lookups-intro:
Distance Lookups
---------------*Availability*: PostGIS, Oracle, SpatiaLite
The following distance lookups are available:
*
*
*
*
*

:lookup:`distance_lt`
:lookup:`distance_lte`
:lookup:`distance_gt`
:lookup:`distance_gte`
:lookup:`dwithin`

.. note::
For *measuring*, rather than querying on distances, use the
:meth:`GeoQuerySet.distance` method.
Distance lookups take a tuple parameter comprising:
#. A geometry to base calculations from; and
#. A number or :class:`~django.contrib.gis.measure.Distance` object containing t
he distance.
If a :class:`~django.contrib.gis.measure.Distance` object is used,
it may be expressed in any units (the SQL generated will use units
converted to those of the field); otherwise, numeric parameters are assumed
to be in the units of the field.
.. note::
For users of PostGIS 1.4 and below, the routine ``ST_Distance_Sphere``
is used by default for calculating distances on geographic coordinate system

s
(e.g., WGS84) -- which may only be called with point geometries [#fndistsphe
re14]_.
Thus, geographic distance lookups on traditional PostGIS geometry columns ar
e
only allowed on :class:`PointField` model fields using a point for the
geometry parameter.
.. note::
In PostGIS 1.5, ``ST_Distance_Sphere`` does *not* limit the geometry types
geographic distance queries are performed with. [#fndistsphere15]_ However,
these queries may take a long time, as great-circle distances must be
calculated on the fly for *every* row in the query. This is because the
spatial index on traditional geometry fields cannot be used.
For much better performance on WGS84 distance queries, consider using
:ref:`geography columns <geography-type>` in your database instead because
they are able to use their spatial index in distance queries.
You can tell GeoDjango to use a geography column by setting ``geography=True
``
in your field definition.
For example, let's say we have a ``SouthTexasCity`` model (from the
`GeoDjango distance tests`__ ) on a *projected* coordinate system valid for citi
es
in southern Texas::
from django.contrib.gis.db import models
class SouthTexasCity(models.Model):
name = models.CharField(max_length=30)
# A projected coordinate system (only valid for South Texas!)
# is used, units are in meters.
point = models.PointField(srid=32140)
objects = models.GeoManager()
Then distance queries may be performed as follows::
>>> from django.contrib.gis.geos import *
>>> from django.contrib.gis.measure import D # ``D`` is a shortcut for ``Dis
tance``
>>> from geoapp import SouthTexasCity
# Distances will be calculated from this point, which does not have to be pr
ojected.
>>> pnt = fromstr('POINT(-96.876369 29.905320)', srid=4326)
# If numeric parameter, units of field (meters in this case) are assumed.
>>> qs = SouthTexasCity.objects.filter(point__distance_lte=(pnt, 7000))
# Find all Cities within 7 km, > 20 miles away, and > 100 chains away (an o
bscure unit)
>>> qs = SouthTexasCity.objects.filter(point__distance_lte=(pnt, D(km=7)))
>>> qs = SouthTexasCity.objects.filter(point__distance_gte=(pnt, D(mi=20)))
>>> qs = SouthTexasCity.objects.filter(point__distance_gte=(pnt, D(chain=100
)))
__ https://github.com/django/django/blob/master/django/contrib/gis/tests/distapp
/models.py
.. _compatibility-table:

Compatibility Tables
====================
.. _spatial-lookup-compatibility:
Spatial Lookups
--------------The following table provides a summary of what spatial lookups are available
for each spatial database backend.
=================================
Lookup Type
=================================
:lookup:`bbcontains`
:lookup:`bboverlaps`
:lookup:`contained`
:lookup:`contains <gis-contains>`
:lookup:`contains_properly`
:lookup:`coveredby`
:lookup:`covers`
:lookup:`crosses`
:lookup:`disjoint`
:lookup:`distance_gt`
:lookup:`distance_gte`
:lookup:`distance_lt`
:lookup:`distance_lte`
:lookup:`dwithin`
:lookup:`equals`
:lookup:`exact`
:lookup:`intersects`
:lookup:`overlaps`
:lookup:`relate`
:lookup:`same_as`
:lookup:`touches`
:lookup:`within`
:lookup:`left`
:lookup:`right`
:lookup:`overlaps_left`
:lookup:`overlaps_right`
:lookup:`overlaps_above`
:lookup:`overlaps_below`
:lookup:`strictly_above`
:lookup:`strictly_below`
=================================

=========
PostGIS
=========
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
=========

======== ============ ==========


Oracle
MySQL [#]_ SpatiaLite
======== ============ ==========
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X

X
X
X
X
X
X
X

X
X
X
X
X
X
X
X
X
X
X
X
X
X

======== ============ ==========

.. _geoqueryset-method-compatibility:
``GeoQuerySet`` Methods
----------------------The following table provides a summary of what :class:`GeoQuerySet` methods
are available on each spatial backend. Please note that MySQL does not
support any of these methods, and is thus excluded from the table.
====================================
Method
====================================
:meth:`GeoQuerySet.area`
:meth:`GeoQuerySet.centroid`
:meth:`GeoQuerySet.collect`

=======
PostGIS
=======
X
X
X

======
Oracle
======
X
X

==========
SpatiaLite
==========
X
X

:meth:`GeoQuerySet.difference`
:meth:`GeoQuerySet.distance`
:meth:`GeoQuerySet.envelope`
:meth:`GeoQuerySet.extent`
:meth:`GeoQuerySet.extent3d`
:meth:`GeoQuerySet.force_rhr`
:meth:`GeoQuerySet.geohash`
:meth:`GeoQuerySet.geojson`
:meth:`GeoQuerySet.gml`
:meth:`GeoQuerySet.intersection`
:meth:`GeoQuerySet.kml`
:meth:`GeoQuerySet.length`
:meth:`GeoQuerySet.make_line`
:meth:`GeoQuerySet.mem_size`
:meth:`GeoQuerySet.num_geom`
:meth:`GeoQuerySet.num_points`
:meth:`GeoQuerySet.perimeter`
:meth:`GeoQuerySet.point_on_surface`
:meth:`GeoQuerySet.reverse_geom`
:meth:`GeoQuerySet.scale`
:meth:`GeoQuerySet.snap_to_grid`
:meth:`GeoQuerySet.svg`
:meth:`GeoQuerySet.sym_difference`
:meth:`GeoQuerySet.transform`
:meth:`GeoQuerySet.translate`
:meth:`GeoQuerySet.union`
:meth:`GeoQuerySet.unionagg`
====================================

X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
=======

X
X

X
X
X

X
X
X
X
X
X
X
X

X
X
X
X
X
X
X
X
X

X
X
X
X
X
X
X
X
====== ==========
X
X

.. rubric:: Footnotes
.. [#fnwkt] *See* Open Geospatial Consortium, Inc., `OpenGIS Simple Feature Spec
ification For SQL <http://www.opengis.org/docs/99-049.pdf>`_, Document 99-049 (M
ay 5, 1999), at Ch. 3.2.5, p. 3-11 (SQL Textual Representation of Geometry).
.. [#fnewkb] *See* `PostGIS EWKB, EWKT and Canonical Forms <http://postgis.refra
ctions.net/documentation/manual-1.5/ch04.html#EWKB_EWKT>`_, PostGIS documentatio
n at Ch. 4.1.2.
.. [#fngeojson] *See* Howard Butler, Martin Daly, Allan Doyle, Tim Schaub, & Chr
istopher Schmidt, `The GeoJSON Format Specification <http://geojson.org/geojsonspec.html>`_, Revision 1.0 (June 16, 2008).
.. [#fndistsphere14] *See* `PostGIS 1.4 documentation <http://postgis.refraction
s.net/documentation/manual-1.4/ST_Distance_Sphere.html>`_ on ``ST_distance_spher
e``.
.. [#fndistsphere15] *See* `PostGIS 1.5 documentation <http://postgis.refraction
s.net/documentation/manual-1.5/ST_Distance_Sphere.html>`_ on ``ST_distance_spher
e``.
.. [#fnmysqlidx] *See* `Creating Spatial Indexes <http://dev.mysql.com/doc/refma
n/5.1/en/creating-spatial-indexes.html>`_
in the MySQL 5.1 Reference Manual:
For MyISAM tables, ``SPATIAL INDEX`` creates an R-tree index. For storage
engines that support nonspatial indexing of spatial columns, the engine
creates a B-tree index. A B-tree index on spatial values will be useful
for exact-value lookups, but not for range scans.
.. [#] Refer :ref:`mysql-spatial-limitations` section for more details.

Vous aimerez peut-être aussi