Version 11 (modified by 17 years ago) ( diff ) | ,
---|
Database API
Note: All GeoDjango queries are performed via the GeoQuerySet
, a modified version of Django's QuerySet
that enables the construction of spatial SQL.
GeoDjango's 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 GeoDjango Model API docs):
>>> qs = Zip.objects.filter(<field>__<lookup_type>=<parameter>) >>> qs = Zip.objects.exclude(...)
For example:
>>> qs = Zip.objects.filter(poly__contains=pnt)
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).
Creating and Saving Geographic Models
Here is an example of how to create a geometry object (assuming the Zip
model):
>>> from zipcode.models import Zip >>> z = Zip(code=77096, poly='POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))') >>> z.save()
GEOSGeometry
objects may also be used to save geometric models:
>>> from django.contrib.gis.geos import GEOSGeometry >>> z = Zip(code=77096, poly=GEOSGeometry('POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))')) >>> 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 = Zip(code=78212, poly=poly_3084) >>> z.save() >>> from django.db import connection >>> print connection.queries[-1]['sql'] # printing the last SQL statement executed INSERT INTO "geoapp_zip" ("code", "poly") VALUES (78212, ST_Transform(ST_GeomFromWKB('\\001 ... ', 3084), 4326))
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.
Below are some examples and references for GEOS Geometry objects, WKT, and HEXEWKB.
- GEOS Geometry:
>>> from django.contrib.gis.geos import * >>> pnt = Point(5, 23) >>> ls = LineString((0, 0), (5, 23)) >>> poly = GEOSGeometry('POLYGON (( 10 10, 10 20, 20 20, 20 15, 10 10))')
- WKT Polygon:
'POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))'
- See Open GIS Consortium, Inc., 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 PostGIS EWKB, EWKT and Canonical Forms, PostGIS documentation at Ch. 4.1.2.
Distance Lookups
Distance lookups are supported on both PostGIS and Oracle. Each distance lookup type takes a tuple parameter comprising (1) a geometry to base calculations from and (2) a number or Distance
object containing the distance. 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.
The following distance lookups are available:
distance_lt
distance_lte
distance_gt
distance_gte
For example, let's say we have a City
model on a projected coordinate system:
from django.contrib.gis.db import models class City(models.Model): name = models.CharField(max_length=30) point = models.PointField(srid=32140) # A projected coordinate system is used, units are in meters. 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 `Distance` >>> from geoapp import City >>> pnt = fromstr('POINT(-96.876369 29.905320)', srid=4326) # Distances will be calculated from this point, which does _not_ have to be projected. >>> qs = City.objects.filter(point__distance_lte=(pnt, 7000)) # If numeric parameter, units of field (meters in this case) are assumed. >>> qs = City.objects.filter(point__distance_lte=(pnt, D(km=7))) # Find all Cities w/in 7km of pnt >>> qs = City.objects.filter(point__distance_gte=(pnt, D(mi=20))) # Find all Cities > 20 miles away from pnt. >>> qs = City.objects.filter(point__distance_gte=(pnt, D(chain=100))) # More obscure units, such as chains, are supported.
PostGIS
PostGIS Operator Field Lookup Types
For more information, see generally, "Operators", PostGIS Documentation at Ch. 6.2.2
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
orexact
- 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
For more information, see generally Geometry Relationship Functions, PostGIS Documentation at Ch. 6.1.2.
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.
equals
- 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
- 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.
- Tuple parameter
(geom, pattern)
required for lookup type, wherepattern
is an intersection pattern -- a string comprising nine characters, where each character is one ofT
,F
, or*
.). - PostGIS equivelent
Relate(geometry, geometry, intersectionPatternMatrix)
The following lookup types are only available in PostGIS versions 1.3.1 and above:
dwithin
- Returns true if geometries are within the specified distance of one another. Uses indexes if available.
- Tuple parameter
(geom, distance)
required for lookup type.
coveredby
- Returns 1 (TRUE) if no point in Geometry A is outside Geometry B
- Refer to this resource for an explaination of the need of this function.
covers
- Returns 1 (TRUE) if no point in Geometry B is outside Geometry A
- See link in
coveredby
documentation above for more information.
Oracle
For more information, see generally, Spatial Operators, Oracle Spatial User's Guide and Manual, at Ch. 11.
contains
- Oracle equivalent
SDO_CONTAINS(geometry1, geometry2)
- Oracle equivalent
coveredby
- Oracle equivalent
SDO_COVEREDBY(geometry1, geometry2)
- Oracle equivalent
covers
- Oracle equivalent
SDO_COVERS(geometry1, geometry2)
- Oracle equivalent
disjoint
- Oracle equivalent
SDO_GEOM.RELATE(geometry1, 'DISJOINT', geometry2, 0.05)
- Oracle equivalent
dwithin
- Oracle equivalent
SDO_WITHIN_DISTANCE(geometry1, geometry2, 'distance=<param>')
- Tuple parameter
(geom, distance)
required for lookup type.
- Oracle equivalent
equals
,exact
,same_as
- Oracle equivalent,
SDO_EQUALS(geometry1, geometry2)
- Oracle equivalent,
intersects
- Oracle equivalent
SDO_OVERLAPBDYINTERSECT(geometry1, geometry2)
- Oracle equivalent
overlaps
- Oracle equivalent
SDO_OVERLAPS(geometry1, geometry2)
- Oracle equivalent
relate
- Oracle equivalent
SDO_RELATE(geometry1, geometry2, <param>)
- 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 relations strings are case-insensitive.- See Oracle Spatial User's Guide & Manual at Ch. 11.
- Oracle equivalent
touches
- Oracle equivalent
SDO_TOUCH(geometry1, geometry2)
- Oracle equivalent
within
- Oracle equivalent
SDO_INSIDE(geometry1, geometry2)
`
- Oracle equivalent
MySQL
For more information, see generally, Relations on Geometry Minimal Bounding Rectangles (MBRs), MySQL 5.0 Reference Manual, at Ch. 17.5.5.
bbcontains
,contains
- MySQL equivalent
MBRContains(g1, g2)
- MySQL equivalent
contained
,within
- MySQL equivalent
MBRWithin(g1, g2)
- MySQL equivalent
disjoint
- MySQL equivalent
MBRDisjoint(g1, g2)
- MySQL equivalent
equals
,exact
,same_as
- MySQL equivalent
MBREqual(g1, g2)
- MySQL equivalent
intersects
- MySQL equivalent
MBRIntersects(g1, g2)
- MySQL equivalent
overlaps
- MySQL equivalent
MBROverlaps(g1, g2)
- MySQL equivalent
touches
- MySQL equivalent
MBRTouches(g1, g2)
- MySQL equivalent
GeoQuerySet Methods
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.
distance
Availability: PostGIS, Oracle
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.
gml
Availability: PostGIS, Oracle
The gml
method attaches a gml
attribute to every model in the queryset that contains the Geographic Markup Language (GML) representation of the geometry.
>>> qs = Zip.objects.all().gml() >>> print qs[0].gml <gml:Polygon srsName="EPSG:4326"><gml:OuterBoundaryIs>-147.78711,70.245363 ... -147.78711,70.245363</gml:OuterBoundaryIs></gml:Polygon>
Keyword arguments:
precision
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.
kml
Availability: PostGIS 1.2.1+
The kml
method attaches a kml
attribute to every model in the queryset that contains the 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.
>>> qs = Zip.objects.all().kml() >>> print qs[0].kml <Polygon><outerBoundaryIs><LinearRing><coordinates>-103.04135,36.217596,0 ... -103.04135,36.217596,0</coordinates></LinearRing></outerBoundaryIs></Polygon>
Keyword arguments:
precision
This keyword may be used to specify the number of significant digits for the coordinates in the KML representation -- the default value is 8.
transform
Availability: PostGIS, Oracle
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.
>>> qs = Zip.objects.all().transform() # Transforms to WGS84 >>> qs = Zip.objects.all().transform(32140) # Transforming to "NAD83 / Texas South Central" >>> print qs[0].poly.srid 32140 >>> print qs[0].poly POLYGON ((234055.1698884720099159 4937796.9232223574072123 ...
Keyword arguments:
srid
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.
union
Availability: PostGIS, Oracle
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.
>>> u = Zip.objects.union() # This may take a LONG time, but returns a geometry representing the union of all Zip code polygons. >>> u = Zip.objects.filter(poly__within=bbox).union() # A more sensible approach.
Keyword arguments:
tolerance
This keyword is only available on Oracle platforms, and is for the tolerance value for SDOAGGRTYPE
. See the Oracle documentation for more details.
Extra Instance Methods
Update: All of the extra instance methods haave 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.