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 contains
are available in GeoDjango when using MySQL, the results returned are really
equivalent to what would be returned when using bbcontains
on a different spatial backend.

Warning

True spatial indexes (R-trees) are only supported with
MyISAM tables on MySQL. [6] 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.

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:

Thus, geometry parameters may be passed in using the GEOSGeometry object, WKT
(Well Known Text [1]), HEXEWKB (PostGIS specific – a WKB geometry in
hexadecimal [2]), and GeoJSON [3] (requires GDAL). Essentially,
if the input is not a GEOSGeometry object, the geometry field will attempt to
create a GEOSGeometry instance from the input.

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. CharField)
may be chained with those on geographic fields. Thus, geographic queries
take the following general form (assuming the Zipcode model used in the
GeoDjango Model API):

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 Selecting an SRID section
in the GeoDjango Model API documentation for more details.

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 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 systems
(e.g., WGS84) – which may only be called with point geometries [4].
Thus, geographic distance lookups on traditional PostGIS geometry columns are
only allowed on 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. [5] 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
geography columns 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 cities
in southern Texas:

fromdjango.contrib.gis.dbimportmodelsclassSouthTexasCity(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:

>>> fromdjango.contrib.gis.geosimport*>>> fromdjango.contrib.gis.measureimportD# ``D`` is a shortcut for ``Distance``>>> fromgeoappimportSouthTexasCity# Distances will be calculated from this point, which does not have to be projected.>>> 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 obscure 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)))

The following table provides a summary of what 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.

For MyISAM tables, SPATIALINDEX 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.