Code

Changes between Version 16 and Version 17 of GeoDjangoDatabaseAPI


Ignore:
Timestamp:
09/05/08 17:48:58 (6 years ago)
Author:
jbronn
Comment:

More up-to-date and comprehensive docs now available at geodjango.org.

Legend:

Unmodified
Added
Removed
Modified
  • GeoDjangoDatabaseAPI

    v16 v17  
    1 [[TOC(GeoDjangoDatabaseAPI)]] 
    2 = Database API = 
     1The !GeoDjango Database API documentation is now located at [http://geodjango.org/docs/db-api.html geodjango.org] 
    32 
    4 '''Note:''' All !GeoDjango queries are performed via the `GeoQuerySet`, a modified version of Django's `QuerySet` that enables the construction of spatial SQL.  
    5  
    6 !GeoDjango's lookup types can only be used 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]): 
    7 {{{ 
    8 #!python 
    9 >>> qs = Zip.objects.filter(<field>__<lookup_type>=<parameter>) 
    10 >>> qs = Zip.objects.exclude(...) 
    11 }}} 
    12  
    13 For example: 
    14 {{{ 
    15 #!python 
    16 >>> qs = Zip.objects.filter(poly__contains=pnt) 
    17 }}} 
    18  
    19 In this case, `poly` is the geographic field, `contains` is the lookup type, and `pnt` is the parameter (which may be a `GEOSGeometry` object, a string of WKT, or a string of HEXEWKB). 
    20  
    21 == Creating and Saving Geographic Models == 
    22 Here is an example of how to create a geometry object (assuming the `Zip` model): 
    23  
    24 {{{ 
    25 #!python 
    26 >>> from zipcode.models import Zip 
    27 >>> z = Zip(code=77096, poly='POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))') 
    28 >>> z.save() 
    29 }}} 
    30  
    31 `GEOSGeometry` objects may also be used to save geometric models: 
    32 {{{ 
    33 #!python 
    34 >>> from django.contrib.gis.geos import GEOSGeometry 
    35 >>> z = Zip(code=77096, poly=GEOSGeometry('POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))')) 
    36 >>> z.save() 
    37 }}} 
    38  
    39 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: 
    40 {{{ 
    41 #!python 
    42 >>> 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' 
    43 >>> z = Zip(code=78212, poly=poly_3084) 
    44 >>> z.save() 
    45 >>> from django.db import connection 
    46 >>> print connection.queries[-1]['sql'] # printing the last SQL statement executed 
    47 INSERT INTO "geoapp_zip" ("code", "poly") VALUES (78212, ST_Transform(ST_GeomFromWKB('\\001 ... ', 3084), 4326)) 
    48 }}} 
    49  
    50 Thus, geometry parameters may be passed in using the `GEOSGeometry` object, WKT (Well Known Text) or HEXEWKB (PostGIS specific, essentially a WKB geometry in hexadecimal).  Essentially, if the input is not a `GEOSGeometry` object, it will attempt to instantiate a `GEOSGeometry` object from the input. 
    51  
    52 Below are some examples and references for GEOS Geometry objects, WKT, and HEXEWKB. 
    53  * GEOS Geometry: 
    54 {{{ 
    55 #!python 
    56 >>> from django.contrib.gis.geos import * 
    57 >>> pnt  = Point(5, 23) 
    58 >>> ls   = LineString((0, 0), (5, 23)) 
    59 >>> poly = GEOSGeometry('POLYGON (( 10 10, 10 20, 20 20, 20 15, 10 10))') 
    60 }}} 
    61  * WKT Polygon: `'POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))'` 
    62    * ''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). 
    63  * HEXEWKB Polygon: '`0103000000010000000 ... 00000000000002440'` 
    64    * ''See'' [http://postgis.refractions.net/docs/ch04.html#id2904792 "PostGIS EWKB, EWKT and Canonical Forms"], PostGIS documentation at Ch. 4.1.2.  
    65  
    66 == Distance Lookups == 
    67 ''Availability'': PostGIS, Oracle 
    68  
    69 Distance lookups take a tuple parameter comprising: 
    70  1. A geometry to base calculations from; and  
    71  2. A number or `Distance` object containing the distance.   
    72  
    73 If a `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 will be assumed to be in the units of the field.   
    74  
    75 '''Note:''' Distance lookups for geodetic coordinate systems was added in r7104 (fixing ticket #6414).  For those using Postgresql, the PostGIS routine `ST_distance_spheroid` is used -- which is limited to calculating distances only to/from points.  Thus, geodetic distance lookups on PostGIS are only allowed with `PointField`s using points as the geographic parameter. 
    76  
    77 The following distance lookups are available: 
    78  
    79  * `distance_lt` 
    80  * `distance_lte` 
    81  * `distance_gt` 
    82  * `distance_gte` 
    83  
    84 For example, let's say we have a `SouthTexasCity` model (from [browser:django/branches/gis/django/contrib/gis/tests/distapp/models.py GeoDjango distance tests]) on a projected coordinate system valid for cities in southern Texas: 
    85 {{{ 
    86 #!python 
    87 from django.contrib.gis.db import models 
    88  
    89 class SouthTexasCity(models.Model): 
    90     name = models.CharField(max_length=30) 
    91     point = models.PointField(srid=32140) # A projected coordinate system (only valid for South Texas!) is used, units are in meters. 
    92     objects = models.GeoManager() 
    93 }}} 
    94 Then distance queries may be performed as follows: 
    95 {{{ 
    96 #!python 
    97 >>> from django.contrib.gis.geos import * 
    98 >>> from django.contrib.gis.measure import D # `D` is a shortcut for `Distance` 
    99 >>> from geoapp import SouthTexasCity  
    100 >>> pnt = fromstr('POINT(-96.876369 29.905320)', srid=4326) # Distances will be calculated from this point, which does _not_ have to be projected. 
    101 >>> qs = SouthTexasCity.objects.filter(point__distance_lte=(pnt, 7000)) # If numeric parameter, units of field (meters in this case) are assumed. 
    102 >>> qs = SouthTexasCity.objects.filter(point__distance_lte=(pnt, D(km=7))) # Find all Cities w/in 7km of pnt 
    103 >>> qs = SouthTexasCity.objects.filter(point__distance_gte=(pnt, D(mi=20))) # Find all Cities > 20 miles away from pnt. 
    104 >>> qs = SouthTexasCity.objects.filter(point__distance_gte=(pnt, D(chain=100))) # More obscure units, such as chains, are supported. 
    105 }}}  
    106  
    107 == PostGIS == 
    108  
    109 === PostGIS Operator Field Lookup Types === 
    110  
    111 For more information, see generally, [http://postgis.refractions.net/docs/ch06.html#id2854381 "Operators", PostGIS Documentation at Ch. 6.2.2] 
    112  * `overlaps_left` 
    113    * Returns true if A's bounding box overlaps or is to the left of B's bounding box. 
    114    * PostGIS equivalent "`&<`" 
    115  * `overlaps_right`  
    116    * Returns true if A's bounding box overlaps or is to the right of B's bounding box. 
    117    * PostGIS equivalent "`&>`" 
    118  * `left` 
    119    * Returns true if A's bounding box is strictly to the left of B's bounding box. 
    120    * PostGIS equivalent "`<<`" 
    121  * `right` 
    122    * Returns true if A's bounding box is strictly to the right of B's bounding box. 
    123    * PostGIS equivalent "`>>`" 
    124  * `overlaps_below` 
    125    * Returns true if A's bounding box overlaps or is below B's bounding box. 
    126    * PostGIS equivalent "`&<|`" 
    127  * `overlaps_above` 
    128    * Returns true if A's bounding box overlaps or is above B's bounding box. 
    129    * PostGIS equivalent "`|&>`" 
    130  * `strictly_below` 
    131    * Returns true if A's bounding box is strictly below B's bounding box. 
    132    * PostGIS equivalent "`<<|`" 
    133  * `strictly_above` 
    134    * Returns true if A's bounding box is strictly above B's bounding box. 
    135    * PostGIS equivalent "`|>>`" 
    136  * `same_as` or `exact` 
    137    * 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. 
    138    * PostGIS equivalent "`~=`" 
    139  * `contained` 
    140    * Returns true if A's bounding box is completely contained by B's bounding box. 
    141    * PostGIS equivalent "`@`" 
    142  * `bbcontains`  
    143    * Returns true if A's bounding box completely contains B's bounding box. 
    144    * PostGIS equivalent "`~`" 
    145  * `bboverlaps` 
    146    * Returns true if A's bounding box overlaps B's bounding box. 
    147    * PostGIS equivalent "`&&`" 
    148  
    149 === PostGIS GEOS Function Field Lookup Types === 
    150 For more information, see generally [http://postgis.refractions.net/docs/ch06.html#id2615853 "Geometry Relationship Functions"], PostGIS Documentation at Ch. 6.1.2. 
    151  
    152 Please note that when using PostGIS 1.3.1 and above, index support is automatically "inlined" -- in other words, the bounding box equivalent is automatically evaluated prior to calling these, more computationally expensive, functions. 
    153  * `equals` 
    154    * Returns 1 (TRUE) if the given Geometries are "spatially equal".  
    155    * Use this for a 'better' answer than '='. equals('LINESTRING(0 0, 10 10)','LINESTRING(0 0, 5 5, 10 10)') is true. 
    156    * PostGIS equivalent `Equals(geometry, geometry)`, OGC SPEC s2.1.1.2 
    157  * `disjoint` 
    158    * Returns 1 (TRUE) if the Geometries are "spatially disjoint". 
    159    * PostGIS equivalent `Disjoint(geometry, geometry)` 
    160  * `touches` 
    161    * Returns 1 (TRUE) if the Geometries "spatially touch". 
    162    * PostGIS equivalent `Touches(geometry, geometry)` 
    163  * `crosses` 
    164    * Returns 1 (TRUE) if the Geometries "spatially cross". 
    165    * PostGIS equivalent `Crosses(geometry, geometry)` 
    166  * `within` 
    167    * Returns 1 (TRUE) if Geometry A is "spatially within" Geometry B. 
    168    * PostGIS equivalent `Within(geometry, geometry)` 
    169  * `overlaps` 
    170    * Returns 1 (TRUE) if the Geometries "spatially overlap". 
    171    * PostGIS equivalent `Overlaps(geometry, geometry)` 
    172  * `contains` 
    173    * Returns 1 (TRUE) if Geometry A "spatially contains" Geometry B. 
    174    * PostGIS equivalent `Contains(geometry, geometry)` 
    175  * `relate` 
    176    * Returns the DE-9IM (dimensionally extended nine-intersection matrix) between the two geometries. 
    177    * Tuple parameter `(geom, pattern)` required for lookup type, where `pattern` is an intersection pattern -- a string comprising nine characters, where each character is one of `T`, `F`, or `*`.). 
    178    * PostGIS equivelent `Relate(geometry, geometry, intersectionPatternMatrix)` 
    179  
    180 The following lookup types are only available in PostGIS versions 1.3.1 and above: 
    181  * `dwithin` 
    182    * Returns true if geometries are within the specified distance of one another. Uses indexes if available. 
    183    * Tuple parameter `(geom, distance)` required for lookup type. 
    184  * `coveredby` 
    185    * Returns 1 (TRUE) if no point in Geometry A is outside Geometry B 
    186    * Refer to [http://lin-ear-th-inking.blogspot.com/2007/06/subtleties-of-ogc-covers-spatial.html this resource] for an explaination of the need of this function. 
    187  * `covers` 
    188    * Returns 1 (TRUE) if no point in Geometry B is outside Geometry A 
    189    * See link in `coveredby` documentation above for more information. 
    190  
    191 == Oracle == 
    192 For more information, see generally, [http://download.oracle.com/docs/html/B14255_01/sdo_operat.htm Spatial Operators], Oracle Spatial User's Guide and Manual, at Ch. 11. 
    193  * `contains` 
    194    * Oracle equivalent `SDO_CONTAINS(geometry1, geometry2)` 
    195  * `coveredby` 
    196    * Oracle equivalent `SDO_COVEREDBY(geometry1, geometry2)` 
    197  * `covers` 
    198    * Oracle equivalent `SDO_COVERS(geometry1, geometry2)` 
    199  * `disjoint` 
    200    * Oracle equivalent `SDO_GEOM.RELATE(geometry1, 'DISJOINT', geometry2, 0.05)` 
    201  * `dwithin` 
    202    * Oracle equivalent `SDO_WITHIN_DISTANCE(geometry1, geometry2, 'distance=<param>')` 
    203    * Tuple parameter `(geom, distance)` required for lookup type. 
    204  * `equals`, `exact`, `same_as` 
    205    * Oracle equivalent, `SDO_EQUALS(geometry1, geometry2)` 
    206  * `intersects` 
    207    * Oracle equivalent `SDO_OVERLAPBDYINTERSECT(geometry1, geometry2)` 
    208  * `overlaps` 
    209    * Oracle equivalent `SDO_OVERLAPS(geometry1, geometry2)` 
    210  * `relate` 
    211    * Oracle equivalent `SDO_RELATE(geometry1, geometry2, <param>)` 
    212    * Tuple parameter `(geom, mask)`, where the mask component is at least one of the nine-intersection patterns: `TOUCH`, `OVERLAPBDYDISJOINT`, `OVERLAPBDYINTERSECT`, `EQUAL`, `INSIDE`, `COVEREDBY`, `CONTAINS`, `COVERS`, `ANYINTERACT`, `ON`. Multiple masks may be combined with the logical Boolean operator OR, for example, '`inside+touch`'.  The mask relation strings are case-insensitive. 
    213      * ''See'' [http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14255/sdo_operat.htm#sthref845 Oracle Spatial User's Guide & Manual] at Ch. 11. 
    214  * `touches` 
    215    * Oracle equivalent `SDO_TOUCH(geometry1, geometry2)` 
    216  * `within` 
    217    * Oracle equivalent `SDO_INSIDE(geometry1, geometry2)` 
    218  
    219 == MySQL == 
    220 For more information, see generally, [http://dev.mysql.com/doc/refman/5.0/en/relations-on-geometry-mbr.html Relations on Geometry Minimal Bounding Rectangles (MBRs)], MySQL 5.0 Reference Manual, at Ch. 17.5.5. 
    221  * `bbcontains`, `contains` 
    222    * MySQL equivalent `MBRContains(g1, g2)` 
    223  * `contained`, `within` 
    224    * MySQL equivalent `MBRWithin(g1, g2)` 
    225  * `disjoint` 
    226    * MySQL equivalent `MBRDisjoint(g1, g2)` 
    227  * `equals`, `exact`, `same_as` 
    228    * MySQL equivalent `MBREqual(g1, g2)` 
    229  * `intersects` 
    230    * MySQL equivalent `MBRIntersects(g1, g2)` 
    231  * `overlaps` 
    232    * MySQL equivalent `MBROverlaps(g1, g2)` 
    233  * `touches` 
    234    * MySQL equivalent `MBRTouches(g1, g2)`  
    235  
    236 = !GeoQuerySet Methods = 
    237  
    238 '''Note:''' All of these methods may take an optional `field_name` keyword parameter that will specify the field on the model to perform the method on.  If no field name is specified, then the first geographic field encountered in the model will be assumed. 
    239  
    240 == distance == 
    241 ''Availability'': PostGIS, Oracle 
    242  
    243 The `distance` method takes a geometry as a parameter, and will attach a `distance` attribute to every model in the returned queryset that contains the distance (in units of the field) to the given geometry.  If a geodetic coordinate system is used (like WGS84), then the `distance` attribute will be in meters.   
    244  
    245 In the following example (from [browser:django/branches/gis/django/contrib/gis/tests/distapp GeoDjango distance tests]), the distance from the Tasmanian city of Hobart to every other `PointField` in the `AustraliaCity` queryset will be calculated.  The `distance` attribute is in meters because the `AustraliaCity` [browser:django/branches/gis/django/contrib/gis/tests/distapp/models.py model] uses WGS84 (the default when no SRID is specified via the `srid` keyword). 
    246 {{{ 
    247 >>> pnt = AustraliaCity.objects.get(name='Hobart').point # See django.contrib.gis.tests.distapp 
    248 >>> for cty in AustraliaCity.objects.distance(pnt): print cty.name, cty.distance 
    249 Wollongong 988817.397733 
    250 Shellharbour 971590.470258 
    251 Thirroul 1001051.96023 
    252 Mittagong 974374.007691 
    253 Batemans Bay 940359.188397 
    254 Canberra 597578.655272 
    255 Melbourne 574635.996781 
    256 Sydney 1055625.32642 
    257 Hobart 0.0 
    258 Adelaide 1162133.07421 
    259 }}}  
    260  
    261 == extent == 
    262 ''Availability'': PostGIS 
    263  
    264 Returns the extent (aggregate) of the features in the `GeoQuerySet`. The extent will be returned as a 4-tuple, consisting of (xmin, ymin, xmax, ymax).  
    265 {{{ 
    266 >>> qs = City.objects.filter(name__in=('Houston', 'Dallas')) 
    267 >>> print qs.extent() 
    268 (-96.8016128540039, 29.7633724212646, -95.3631439208984, 32.782058715820) 
    269 }}} 
    270  
    271 == gml == 
    272 ''Availability'': PostGIS, Oracle 
    273  
    274 The `gml` method attaches a `gml` attribute to every model in the queryset that contains the [http://en.wikipedia.org/wiki/Geography_Markup_Language Geographic Markup Language] (GML) representation of the geometry. 
    275 {{{ 
    276 >>> qs = Zip.objects.all().gml() 
    277 >>> print qs[0].gml 
    278 <gml:Polygon srsName="EPSG:4326"><gml:OuterBoundaryIs>-147.78711,70.245363 ...  -147.78711,70.245363</gml:OuterBoundaryIs></gml:Polygon> 
    279 }}} 
    280  
    281 Keyword arguments: 
    282 === precision === 
    283 This keyword may be used to specify the number of significant digits for the coordinates in the GML representation -- the default value is 8.  This keyword may not be used on Oracle. 
    284  
    285 == kml == 
    286  
    287 ''Availability'': PostGIS 1.2.1+ 
    288  
    289 The `kml` method attaches a `kml` attribute to every model in the queryset that contains the [http://code.google.com/apis/kml/documentation/ Keyhole Markup Language] (KML) representation of the geometry.  It should be noted that the contents of the KML are in WGS84, and will be transformed if necessary -- the geometry field attribute itself is not affected. 
    290  
    291 {{{ 
    292 >>> qs = Zip.objects.all().kml() 
    293 >>> print qs[0].kml 
    294 <Polygon><outerBoundaryIs><LinearRing><coordinates>-103.04135,36.217596,0 ... -103.04135,36.217596,0</coordinates></LinearRing></outerBoundaryIs></Polygon> 
    295 }}} 
    296  
    297 Keyword arguments: 
    298 === precision === 
    299 This keyword may be used to specify the number of significant digits for the coordinates in the KML representation -- the default value is 8. 
    300  
    301 == transform == 
    302 ''Availability'': PostGIS, Oracle 
    303  
    304 The `transform` method transforms the geometries in a model to a different spatial reference system.  If the `srid` parameter is not specified, WGS84 is used by default. 
    305  
    306 {{{ 
    307 >>> qs = Zip.objects.all().transform() # Transforms to WGS84 
    308 >>> qs = Zip.objects.all().transform(32140) # Transforming to "NAD83 / Texas South Central" 
    309 >>> print qs[0].poly.srid 
    310 32140 
    311 >>> print qs[0].poly 
    312 POLYGON ((234055.1698884720099159 4937796.9232223574072123 ... 
    313 }}} 
    314  
    315 Keyword arguments: 
    316 === srid === 
    317 The `srid` keyword may be used to specify the spatial reference system identifier.  Please note that this may depend on your spatial database backend, ''e.g.'', those used for Oracle are not the same as those used by PostGIS. 
    318  
    319 == union == 
    320 ''Availability'': PostGIS, Oracle 
    321  
    322 This `union` method returns a `GEOSGeometry` object comprising the union of every geometry in the queryset.  Please note that use of `union` is processor intensive and may take a significant amount of time on large querysets. 
    323  
    324 {{{ 
    325 >>> u = Zip.objects.union() # This may take a LONG time, but returns a geometry representing the union of all Zip code polygons. 
    326 >>> u = Zip.objects.filter(poly__within=bbox).union() # A more sensible approach. 
    327 }}} 
    328  
    329 Keyword arguments: 
    330 === tolerance === 
    331 This keyword is only available on Oracle platforms, and is for the tolerance value for `SDOAGGRTYPE`.  ''See'' the Oracle [http://download.oracle.com/docs/html/B14255_01/sdo_intro.htm#sthref150 documentation] for more details. 
    332  
    333 = Extra Instance Methods = 
    334 '''Update:''' All of the extra instance methods have been deprecated as of r6467 because lazy geometry support includes all of their functionality (including OGR geometries and OSR spatial references with the `ogr` and `srs` properties, respectively).  In other words, these properties may be directly accessed as attributes from the geometry field. 
     3Feel free to leave comments and/or suggestions about the !GeoDjango Database API documentation here.