[[TOC(GeoDjangoDatabaseAPI)]] = Database API = '''Note:''' The following database lookup types can only be used with on geographic fields with {{{filter()}}}. Filters on 'normal' fields (e.g. {{{CharField}}}) may be chained with those on geographic fields. Thus, geographic queries take the following form (assuming the {{{Zip}}} model used in the [wiki:GeoDjangoModelAPI GeoDjango Model API docs]: {{{ #!python >>> qs = Zip.objects.filter(__=) >>> qs = Zip.objects.exclude(...) }}} == Creating and Saving Geographic-Enabled Objects == Here is an example of how to create a geometry object (assuming the {{{Zip}}} model example above): {{{ #!python >>> from zipcode.models import Zip >>> z = Zip(code=77096, poly='POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))') >>> z.save() }}} Geometries are represented as '''strings''' in either of the formats WKT (Well Known Text) or HEXEWKB (PostGIS specific, essentially a WKB geometry in hexadecimal). For example: * WKT Polygon: {{{'POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))'}}} * ''See'' Open GIS Consortium, Inc., ''[http://www.opengis.org/docs/99-049.pdf OpenGIS Simple Feature Specification For SQL]'', Document 99-049 (May 5, 1999), at Ch. 3.2.5 (SQL Textual Representation of Geometry, pg. 53). * HEXEWKB Polygon: '{{{0103000000010000000 ... 00000000000002440'}}} * ''See'' [http://postgis.refractions.net/docs/ch04.html#id2904792 "PostGIS EWKB, EWKT and Canonical Forms"], PostGIS documentation at Ch. 4.1.2. == PostGIS Operator Field Lookup Types == * ''See generally'', [http://postgis.refractions.net/docs/ch06.html#id2854381 "Operators", PostGIS Documentation at Ch. 6.2.2] * '''Note:''' This API is subject to some change -- we're open to suggestions. * {{{overlaps_left}}} * Returns true if A's bounding box overlaps or is to the left of B's bounding box. * PostGIS equivalent "{{{&<}}}" * {{{overlaps_right}}} * Returns true if A's bounding box overlaps or is to the right of B's bounding box. * PostGIS equivalent "{{{&>}}}" * {{{left}}} * Returns true if A's bounding box is strictly to the left of B's bounding box. * PostGIS equivalent "{{{<<}}}" * {{{right}}} * Returns true if A's bounding box is strictly to the right of B's bounding box. * PostGIS equivalent "{{{>>}}}" * {{{overlaps_below}}} * Returns true if A's bounding box overlaps or is below B's bounding box. * PostGIS equivalent "{{{&<|}}}" * {{{overlaps_above}}} * Returns true if A's bounding box overlaps or is above B's bounding box. * PostGIS equivalent "{{{|&>}}}" * {{{strictly_below}}} * Returns true if A's bounding box is strictly below B's bounding box. * PostGIS equivalent "{{{<<|}}}" * {{{strictly_above}}} * Returns true if A's bounding box is strictly above B's bounding box. * PostGIS equivalent "{{{|>>}}}" * {{{same_as}}} or {{{exact}}} * The "same as" operator. It tests actual geometric equality of two features. So if A and B are the same feature, vertex-by-vertex, the operator returns true. * PostGIS equivalent "{{{~=}}}" * {{{contained}}} * Returns true if A's bounding box is completely contained by B's bounding box. * PostGIS equivalent "{{{@}}}" * {{{bbcontains}}} * Returns true if A's bounding box completely contains B's bounding box. * PostGIS equivalent "{{{~}}}" * {{{bboverlaps}}} * Returns true if A's bounding box overlaps B's bounding box. * PostGIS equivalent "{{{&&}}}" == PostGIS GEOS Function Field Lookup Types == * ''See generally'' [http://postgis.refractions.net/docs/ch06.html#id2615853 "Geometry Relationship Functions", PostGIS Documentation at Ch. 6.1.2]. * This documentation will be updated completely with the content from the aforementioned PostGIS docs. * {{{equals}}} * Requires GEOS * Returns 1 (TRUE) if the given Geometries are "spatially equal". * Use this for a 'better' answer than '='. equals('LINESTRING(0 0, 10 10)','LINESTRING(0 0, 5 5, 10 10)') is true. * PostGIS equivalent {{{Equals(geometry, geometry)}}}, OGC SPEC s2.1.1.2 * {{{disjoint}}} * Requires GEOS * Returns 1 (TRUE) if the Geometries are "spatially disjoint". * PostGIS equivalent {{{Disjoint(geometry, geometry)}}} * {{{touches}}} * Returns 1 (TRUE) if the Geometries "spatially touch". * PostGIS equivalent {{{Touches(geometry, geometry)}}} * {{{crosses}}} * Returns 1 (TRUE) if the Geometries "spatially cross". * PostGIS equivalent {{{Crosses(geometry, geometry)}}} * {{{within}}} * Returns 1 (TRUE) if Geometry A is "spatially within" Geometry B. * PostGIS equivalent {{{Within(geometry, geometry)}}} * {{{overlaps}}} * Returns 1 (TRUE) if the Geometries "spatially overlap". * PostGIS equivalent {{{Overlaps(geometry, geometry)}}} * {{{contains}}} * Returns 1 (TRUE) if Geometry A "spatially contains" Geometry B. * PostGIS equivalent {{{Contains(geometry, geometry)}}} * {{{relate}}} * Returns the DE-9IM (dimensionally extended nine-intersection matrix) between the two geometries. * PostGIS equivelent {{{Relate(geometry, geometry)}}} = Extra Instance Methods = A model with geometry fields will get the following methods, substitute {{{GEOM}}} with the name of the geometry field. '''Update:''' All of the extra instance methods below (except {{{get_GEOM_ogr}}} and {{{get_GEOM_srs}}}) have been deprecated in r5657 due to lazy geometry support. In other words, these properties may be directly accessed as attributes from the geometry field. As part of the deprecation process, [http://docs.python.org/lib/module-warnings.html warnings] are issued when such methods are invoked so that users have notice to change their code before these methods disappear in the future. == get_GEOM_ogr == Returns a {{{OGRGeometry}}} instance for the geometry. For example, using the {{{Zip}}} model, as above: {{{ #!python >>> from django.contrib.gis.gdal import OGRGeometry # Where to import from >>> z = Zip.objects.get(code='77096') >>> geom = z.get_poly_ogr() >>> print geom POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10)) >>> for ring in poly: ... print ring ... for point in ring: ... print point ... LINEARRING (10 10,10 20,20 20,20 15,10 10) (10.0, 10.0) (10.0, 20.0) (20.0, 20.0) (20.0, 15.0) (10.0, 10.0) }}} == get_GEOM_srs == Returns the OGR {{{SpatialReference}}} object for this geometry. {{{ #!python >>> from django.contrib.gis.gdal import SpatialReference # Where these related classes reside >>> z = Zip.objects.get(code='77096') >>> srs = z.get_poly_srs() >>> print srs GEOGCS["WGS 84", DATUM["WGS_1984", SPHEROID["WGS 84",6378137,298.257223563, AUTHORITY["EPSG","7030"]], TOWGS84[0,0,0,0,0,0,0], AUTHORITY["EPSG","6326"]], PRIMEM["Greenwich",0, AUTHORITY["EPSG","8901"]], UNIT["degree",0.01745329251994328, AUTHORITY["EPSG","9122"]], AUTHORITY["EPSG","4326"]] >>> print srs.semi_major, srs.semi_minor, srs.inverse_flattening 6378137.0 6356752.31425 298.257223563 >>> print srs.geographic True }}} == get_GEOM_geos == '''Update:''' This extra instance method was deprecated in r5657 -- and may now be accessed directly through the attribute name of the geometry field -- ''e.g.'', {{{dist.poly}}} returns a {{{GEOSGeometry}}} instance for the {{{PolygonField}}} of the {{{District}}} model. Returns a {{{GEOSGeometry}}} instance for the geometry. For example (using the {{{District}}} model from the [wiki:GeoDjango#Example example]): {{{ #!python >>> from django.contrib.gis.geos import GEOSGeometry # Where to import from >>> dist = District.objects.get(name='Houston ISD') >>> geom = dist.get_poly_geos() >>> print geom.centroid.wkt POINT(-95.231713 29.723235) >>> print geom.area 0.08332 >>> print geom.geom_type Polygon >>> print geom.centroid.geom_type Point >>> print geom.intersects(GEOSGeometry('POINT(-95.395223 29.798088)')) False }}} == get_GEOM_srid == '''Update:''' This extra instance method was deprecated in r5657 -- and may now be accessed directly through the attribute name of the geometry field -- ''e.g.'', {{{dist.poly.srid}}}. Returns the SRID (source reference identifier) for the geometry. == get_GEOM_wkt == '''Update:''' This extra instance method was deprecated in r5657 -- and may now be accessed directly through the attribute name of the geometry field -- ''e.g.'', {{{skool.point.wkt}}}, or simply {{{str(skool.point)}}}. Returns the OGC WKT (Well Known Text) for the geometry. For example (using the {{{School}}} model from the [wiki:GeoDjango#Example example]): {{{ #!python >>> skool = School.objects.get(name='PSAS') >>> print skool.get_point_wkt() POINT(-95.460822 29.745463) }}} == get_GEOM_centroid == '''Update:''' This extra instance method was deprecated in r5657 -- and may now be accessed directly through the attribute name of the geometry field -- ''e.g.'', {{{dist.poly.centroid.wkt}}}. This routine will return the centroid of the geometry. For example (using the {{{District}}} model from above): {{{ #!python >>> dist = District.objects.get(name='Houston ISD') >>> print dist.get_poly_centroid() POINT(-95.231713 29.723235) }}} == get_GEOM_area == '''Update:''' This extra instance method was deprecated in r5657 -- and may now be accessed directly through the attribute name of the geometry field -- ''e.g.'', {{{dist.poly.area}}}. This routine will return the area of the geometry field. {{{ #!python >>> dist = District.objects.get(name='Houston ISD') >>> print dist.get_poly_area() 0.08332 }}} '''Note''': Units are in the projected units of the coordinate system. In the example above, the units are in degrees since we're using WGS84.