db-api.txt 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. .. _ref-gis-db-api:
  2. ======================
  3. GeoDjango Database API
  4. ======================
  5. .. module:: django.contrib.gis.db.models
  6. :synopsis: GeoDjango's database API.
  7. .. _spatial-backends:
  8. Spatial Backends
  9. ================
  10. .. versionadded:: 1.2
  11. In Django 1.2, support for :ref:`multiple databases <topics-db-multi-db>` was
  12. introduced. In order to support multiple databases, GeoDjango has segregated
  13. its functionality into full-fledged spatial database backends:
  14. * :mod:`django.contrib.gis.db.backends.postgis`
  15. * :mod:`django.contrib.gis.db.backends.mysql`
  16. * :mod:`django.contrib.gis.db.backends.oracle`
  17. * :mod:`django.contrib.gis.db.backends.spatialite`
  18. Backwards-Compatibility
  19. -----------------------
  20. For those using the old database settings (e.g., the ``DATABASE_*`` settings)
  21. Django 1.2 will automatically use the appropriate spatial backend as long
  22. as :mod:`django.contrib.gis` is in your :setting:`INSTALLED_APPS`. For
  23. example, if you have the following in your settings::
  24. DATABASE_ENGINE='postgresql_psycopg2'
  25. ...
  26. INSTALLED_APPS = (
  27. ...
  28. 'django.contrib.gis',
  29. ...
  30. )
  31. Then, :mod:`django.contrib.gis.db.backends.postgis` will automatically be used as your
  32. spatial backend.
  33. Creating and Saving Geographic Models
  34. =====================================
  35. Here is an example of how to create a geometry object (assuming the ``Zipcode``
  36. model)::
  37. >>> from zipcode.models import Zipcode
  38. >>> z = Zipcode(code=77096, poly='POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))')
  39. >>> z.save()
  40. :class:`~django.contrib.gis.geos.GEOSGeometry` objects may also be used to save geometric models::
  41. >>> from django.contrib.gis.geos import GEOSGeometry
  42. >>> poly = GEOSGeometry('POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))')
  43. >>> z = Zipcode(code=77096, poly=poly)
  44. >>> z.save()
  45. Moreover, if the ``GEOSGeometry`` is in a different coordinate system (has a
  46. different SRID value) than that of the field, then it will be implicitly
  47. transformed into the SRID of the model's field, using the spatial database's
  48. transform procedure::
  49. >>> 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'
  50. >>> z = Zipcode(code=78212, poly=poly_3084)
  51. >>> z.save()
  52. >>> from django.db import connection
  53. >>> print connection.queries[-1]['sql'] # printing the last SQL statement executed (requires DEBUG=True)
  54. INSERT INTO "geoapp_zipcode" ("code", "poly") VALUES (78212, ST_Transform(ST_GeomFromWKB('\\001 ... ', 3084), 4326))
  55. Thus, geometry parameters may be passed in using the ``GEOSGeometry`` object, WKT
  56. (Well Known Text [#fnwkt]_), HEXEWKB (PostGIS specific -- a WKB geometry in
  57. hexadecimal [#fnewkb]_), and GeoJSON [#fngeojson]_ (requires GDAL). Essentially,
  58. if the input is not a ``GEOSGeometry`` object, the geometry field will attempt to
  59. create a ``GEOSGeometry`` instance from the input.
  60. For more information creating :class:`~django.contrib.gis.geos.GEOSGeometry`
  61. objects, refer to the :ref:`GEOS tutorial <geos-tutorial>`.
  62. .. _spatial-lookups-intro:
  63. Spatial Lookups
  64. ===============
  65. GeoDjango's lookup types may be used with any manager method like
  66. ``filter()``, ``exclude()``, etc. However, the lookup types unique to
  67. GeoDjango are only available on geometry fields.
  68. Filters on 'normal' fields (e.g. :class:`~django.db.models.CharField`)
  69. may be chained with those on geographic fields. Thus, geographic queries
  70. take the following general form (assuming the ``Zipcode`` model used in the
  71. :ref:`ref-gis-model-api`)::
  72. >>> qs = Zipcode.objects.filter(<field>__<lookup_type>=<parameter>)
  73. >>> qs = Zipcode.objects.exclude(...)
  74. For example::
  75. >>> qs = Zipcode.objects.filter(poly__contains=pnt)
  76. In this case, ``poly`` is the geographic field, :lookup:`contains <gis-contains>`
  77. is the spatial lookup type, and ``pnt`` is the parameter (which may be a
  78. :class:`~django.contrib.gis.geos.GEOSGeometry` object or a string of
  79. GeoJSON , WKT, or HEXEWKB).
  80. A complete reference can be found in the :ref:`spatial lookup reference
  81. <spatial-lookups>`.
  82. .. note::
  83. GeoDjango constructs spatial SQL with the :class:`GeoQuerySet`, a
  84. subclass of :class:`~django.db.models.QuerySet`. The
  85. :class:`GeoManager` instance attached to your model is what
  86. enables use of :class:`GeoQuerySet`.
  87. .. _distance-queries:
  88. Distance Queries
  89. ================
  90. Introduction
  91. ------------
  92. Distance calculations with spatial data is tricky because, unfortunately,
  93. the Earth is not flat. Some distance queries with fields in a geographic
  94. coordinate system may have to be expressed differently because of
  95. limitations in PostGIS. Please see the :ref:`selecting-an-srid` section
  96. in the :ref:`ref-gis-model-api` documentation for more details.
  97. .. _distance-lookups-intro:
  98. Distance Lookups
  99. ----------------
  100. *Availability*: PostGIS, Oracle, SpatiaLite
  101. The following distance lookups are available:
  102. * :lookup:`distance_lt`
  103. * :lookup:`distance_lte`
  104. * :lookup:`distance_gt`
  105. * :lookup:`distance_gte`
  106. * :lookup:`dwithin`
  107. .. note::
  108. For *measuring*, rather than querying on distances, use the
  109. :meth:`GeoQuerySet.distance` method.
  110. Distance lookups take a tuple parameter comprising:
  111. #. A geometry to base calculations from; and
  112. #. A number or :class:`~django.contrib.gis.measure.Distance` object containing the distance.
  113. If a :class:`~django.contrib.gis.measure.Distance` object is used,
  114. it may be expressed in any units (the SQL generated will use units
  115. converted to those of the field); otherwise, numeric parameters are assumed
  116. to be in the units of the field.
  117. .. note::
  118. For PostGIS users, the routine ``ST_distance_sphere``
  119. is used by default for calculating distances on geographic coordinate systems
  120. -- which may only be called with point geometries [#fndistsphere]_. Thus,
  121. geographic distance lookups on traditional PostGIS geometry columns are
  122. only allowed on :class:`PointField` model fields using a point for the
  123. geometry parameter.
  124. .. note::
  125. PostGIS 1.5 introduced :ref:`geography columns <geography-type>`, which
  126. is limited on what geometry types distance queries are performed with. In
  127. other words, if you have ``geography=True`` in your geometry field
  128. definition you'll be allowed to peform arbitrary distance queries with your
  129. data in geodetic units of WGS84.
  130. For example, let's say we have a ``SouthTexasCity`` model (from the
  131. `GeoDjango distance tests`__ ) on a *projected* coordinate system valid for cities
  132. in southern Texas::
  133. from django.contrib.gis.db import models
  134. class SouthTexasCity(models.Model):
  135. name = models.CharField(max_length=30)
  136. # A projected coordinate system (only valid for South Texas!)
  137. # is used, units are in meters.
  138. point = models.PointField(srid=32140)
  139. objects = models.GeoManager()
  140. Then distance queries may be performed as follows::
  141. >>> from django.contrib.gis.geos import *
  142. >>> from django.contrib.gis.measure import D # ``D`` is a shortcut for ``Distance``
  143. >>> from geoapp import SouthTexasCity
  144. # Distances will be calculated from this point, which does not have to be projected.
  145. >>> pnt = fromstr('POINT(-96.876369 29.905320)', srid=4326)
  146. # If numeric parameter, units of field (meters in this case) are assumed.
  147. >>> qs = SouthTexasCity.objects.filter(point__distance_lte=(pnt, 7000))
  148. # Find all Cities within 7 km, > 20 miles away, and > 100 chains away (an obscure unit)
  149. >>> qs = SouthTexasCity.objects.filter(point__distance_lte=(pnt, D(km=7)))
  150. >>> qs = SouthTexasCity.objects.filter(point__distance_gte=(pnt, D(mi=20)))
  151. >>> qs = SouthTexasCity.objects.filter(point__distance_gte=(pnt, D(chain=100)))
  152. __ http://code.djangoproject.com/browser/django/trunk/django/contrib/gis/tests/distapp/models.py
  153. .. _compatibility-table:
  154. Compatibility Tables
  155. ====================
  156. .. _spatial-lookup-compatibility:
  157. Spatial Lookups
  158. ---------------
  159. The following table provides a summary of what spatial lookups are available
  160. for each spatial database backend.
  161. ================================= ========= ======== ============ ==========
  162. Lookup Type PostGIS Oracle MySQL [#]_ SpatiaLite
  163. ================================= ========= ======== ============ ==========
  164. :lookup:`bbcontains` X X X
  165. :lookup:`bboverlaps` X X X
  166. :lookup:`contained` X X X
  167. :lookup:`contains <gis-contains>` X X X X
  168. :lookup:`contains_properly` X
  169. :lookup:`coveredby` X X
  170. :lookup:`covers` X X
  171. :lookup:`crosses` X X
  172. :lookup:`disjoint` X X X X
  173. :lookup:`distance_gt` X X X
  174. :lookup:`distance_gte` X X X
  175. :lookup:`distance_lt` X X X
  176. :lookup:`distance_lte` X X X
  177. :lookup:`dwithin` X X
  178. :lookup:`equals` X X X X
  179. :lookup:`exact` X X X X
  180. :lookup:`intersects` X X X X
  181. :lookup:`overlaps` X X X X
  182. :lookup:`relate` X X X
  183. :lookup:`same_as` X X X X
  184. :lookup:`touches` X X X X
  185. :lookup:`within` X X X X
  186. :lookup:`left` X
  187. :lookup:`right` X
  188. :lookup:`overlaps_left` X
  189. :lookup:`overlaps_right` X
  190. :lookup:`overlaps_above` X
  191. :lookup:`overlaps_below` X
  192. :lookup:`strictly_above` X
  193. :lookup:`strictly_below` X
  194. ================================= ========= ======== ============ ==========
  195. .. _geoqueryset-method-compatibility:
  196. ``GeoQuerySet`` Methods
  197. -----------------------
  198. The following table provides a summary of what :class:`GeoQuerySet` methods
  199. are available on each spatial backend. Please note that MySQL does not
  200. support any of these methods, and is thus excluded from the table.
  201. ==================================== ======= ====== ==========
  202. Method PostGIS Oracle SpatiaLite
  203. ==================================== ======= ====== ==========
  204. :meth:`GeoQuerySet.area` X X X
  205. :meth:`GeoQuerySet.centroid` X X X
  206. :meth:`GeoQuerySet.collect` X
  207. :meth:`GeoQuerySet.difference` X X X
  208. :meth:`GeoQuerySet.distance` X X X
  209. :meth:`GeoQuerySet.envelope` X X
  210. :meth:`GeoQuerySet.extent` X X
  211. :meth:`GeoQuerySet.extent3d` X
  212. :meth:`GeoQuerySet.force_rhr` X
  213. :meth:`GeoQuerySet.geohash` X
  214. :meth:`GeoQuerySet.geojson` X
  215. :meth:`GeoQuerySet.gml` X X
  216. :meth:`GeoQuerySet.intersection` X X X
  217. :meth:`GeoQuerySet.kml` X
  218. :meth:`GeoQuerySet.length` X X X
  219. :meth:`GeoQuerySet.make_line` X
  220. :meth:`GeoQuerySet.mem_size` X
  221. :meth:`GeoQuerySet.num_geom` X X X
  222. :meth:`GeoQuerySet.num_points` X X X
  223. :meth:`GeoQuerySet.perimeter` X X
  224. :meth:`GeoQuerySet.point_on_surface` X X X
  225. :meth:`GeoQuerySet.reverse_geom` X X
  226. :meth:`GeoQuerySet.scale` X X
  227. :meth:`GeoQuerySet.snap_to_grid` X
  228. :meth:`GeoQuerySet.svg` X X
  229. :meth:`GeoQuerySet.sym_difference` X X X
  230. :meth:`GeoQuerySet.transform` X X X
  231. :meth:`GeoQuerySet.translate` X X
  232. :meth:`GeoQuerySet.union` X X X
  233. :meth:`GeoQuerySet.unionagg` X X X
  234. ==================================== ======= ====== ==========
  235. .. rubric:: Footnotes
  236. .. [#fnwkt] *See* Open Geospatial Consortium, Inc., `OpenGIS Simple Feature Specification For SQL <http://www.opengis.org/docs/99-049.pdf>`_, Document 99-049 (May 5, 1999), at Ch. 3.2.5, p. 3-11 (SQL Textual Representation of Geometry).
  237. .. [#fnewkb] *See* `PostGIS EWKB, EWKT and Canonical Forms <http://postgis.refractions.net/documentation/manual-1.5/ch04.html#EWKB_EWKT>`_, PostGIS documentation at Ch. 4.1.2.
  238. .. [#fngeojson] *See* Howard Butler, Martin Daly, Allan Doyle, Tim Schaub, & Christopher Schmidt, `The GeoJSON Format Specification <http://geojson.org/geojson-spec.html>`_, Revision 1.0 (June 16, 2008).
  239. .. [#fndistsphere] *See* PostGIS 1.5 ``ST_distance_sphere`` `documentation <http://postgis.refractions.net/documentation/manual-1.5/ST_Distance_Sphere.html>`_.
  240. .. [#] MySQL only supports bounding box operations (known as minimum bounding rectangles, or MBR, in MySQL). Thus, spatial lookups such as :lookup:`contains <gis-contains>` are really equivalent to :lookup:`bbcontains`.