GeoDjango Database API

Spatial Backends

GeoDjango目前提供以下空间数据库后端:

  • django.contrib.gis.db.backends.postgis
  • django.contrib.gis.db.backends.mysql
  • django.contrib.gis.db.backends.oracle
  • django.contrib.gis.db.backends.spatialite

MySQL Spatial Limitations

MySQL的空间扩展只支持边界框操作(什么MySQL调用最小边界矩形,或MBR)。具体来说,MySQL不符合OGC标准

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.

换句话说,虽然在使用MySQL时,在GeoDjango中可以使用contains的空间查找,但返回的结果实际上等效于在不同的空间上使用bbcontains后端。

警告

只有MySQL上的MyISAM表支持真空间索引(R-树)。[5]换句话说,当使用MySQL空间扩展时,必须在快速空间查找和数据完整性之间进行选择 - MyISAM表不支持事务或外键约束。

Creating and Saving Geographic Models

下面是一个如何创建几何对象的示例(假设Zipcode模型):

>>> from zipcode.models import Zipcode
>>> z = Zipcode(code=77096, poly='POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))')
>>> z.save()

GEOSGeometry对象也可用于保存几何模型:

>>> from django.contrib.gis.geos import GEOSGeometry
>>> poly = GEOSGeometry('POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))')
>>> z = Zipcode(code=77096, poly=poly)
>>> z.save()

此外,如果GEOSGeometry位于与该字段不同的坐标系中(具有不同的SRID值),则将使用空间数据库的变换将其隐式转换为模型字段的SRID程序:

>>> 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 = Zipcode(code=78212, poly=poly_3084)
>>> z.save()
>>> from django.db import connection
>>> print(connection.queries[-1]['sql']) # printing the last SQL statement executed (requires DEBUG=True)
INSERT INTO "geoapp_zipcode" ("code", "poly") VALUES (78212, ST_Transform(ST_GeomFromWKB('\\001 ... ', 3084), 4326))

因此,可以使用GEOSGeometry对象,WKT(井已知文本[1]),HEXEWKB(PostGIS特定 - 十六进制的WKB几何[2])和GeoJSON [3](需要GDAL)。实质上,如果输入不是GEOSGeometry对象,则几何字段将尝试从输入创建GEOSGeometry实例。

有关创建GEOSGeometry对象的更多信息,请参阅GEOS tutorial

Spatial Lookups

GeoDjango的查找类型可以用于任何管理器方法,例如filter()exclude()等。但是,GeoDjango唯一的查找类型仅适用于几何字段。“正常”字段的过滤器(例如CharField)可以与地理字段上的链接。因此,地理查询采用以下一般形式(假设GeoDjango Model API中使用的Zipcode模型):

>>> qs = Zipcode.objects.filter(<field>__<lookup_type>=<parameter>)
>>> qs = Zipcode.objects.exclude(...)

例如:

>>> qs = Zipcode.objects.filter(poly__contains=pnt)

在这种情况下,poly是地理字段,contains是空间查找类型,pnt是参数(可以是GEOSGeometry对象或GeoJSON,WKT或HEXEWKB的字符串)。

完整的引用可以在spatial lookup reference中找到。

注意

GeoDjango使用GeoQuerySetQuerySet的子类)构造空间SQL。附加到模型的GeoManager实例可启用GeoQuerySet的使用。

Distance Queries

Introduction

使用空间数据的距离计算很棘手,因为不幸的是,地球不平。由于PostGIS中的限制,具有地理坐标系中的字段的一些距离查询可能必须被不同地表示。有关详情,请参阅GeoDjango Model API文档中的Selecting an SRID部分。

Distance Lookups

可用性:PostGIS,Oracle,SpatiaLite

以下距离查找可用:

注意

对于测量,而不是查询距离,请使用GeoQuerySet.distance()方法。

距离查找采用元组参数,包括:

  1. 基于计算的几何图形;和
  2. 包含距离的数字或Distance对象。

如果使用Distance对象,它可以以任何单位表示(生成的SQL将使用转换为字段的单位的单位);否则,假设数字参数以字段为单位。

注意

在PostGIS中,ST_Distance_Sphere 限制使用地理距离查询执行的几何类型。[4]但是,这些查询可能需要很长时间,因为必须为查询中的行动态计算大圆距离。这是因为传统几何字段上的空间索引不能使用。

要在WGS84距离查询上获得更好的性能,请考虑在数据库中使用geography columns,因为它们能够在距离查询中使用其空间索引。您可以通过在字段定义中设置geography=True来让GeoDjango使用地理位置列。

例如,假设我们在有效于得克萨斯州南部城市的投影坐标系统上有SouthTexasCity模型(从GeoDjango距离测试

from django.contrib.gis.db import models

class SouthTexasCity(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()

然后可以如下执行距离查询:

>>> from django.contrib.gis.geos import *
>>> from django.contrib.gis.measure import D # ``D`` is a shortcut for ``Distance``
>>> from geoapp import SouthTexasCity
# 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)))

Compatibility Tables

Spatial Lookups

下表提供了每个空间数据库后端可用的空间查找的摘要。

查找类型PostGISOracleMySQL [6]SpatiaLite
bbcontainsXXX
bboverlapsXXX
containedXXX
containsXXXX
contains_properlyX
coveredbyXX
coversXX
crossesXX
disjointXXXX
distance_gtXXX
distance_gteXXX
distance_ltXXX
distance_lteXXX
dwithinXX
equalsXXXX
exactXXXX
intersectsXXXX
overlapsXXXX
relateXXX
same_asXXXX
touchesXXXX
withinXXXX
leftX
rightX
overlaps_leftX
overlaps_rightX
overlaps_aboveX
overlaps_belowX
strictly_aboveX
strictly_belowX

Aggregate Functions

下表提供了每个空间后端可用的特定于GIS的聚合函数的摘要。请注意,MySQL不支持任何这些聚合,因此从表中排除。

骨料PostGISOracleSpatiaLite
CollectX(从v3.0)
ExtentXX(从v3.0)
Extent3DX
MakeLineX
UnionXXX

脚注

[1]请参阅 Open Geospatial Consortium,Inc.,OpenGIS Simple Feature Specification For SQL,Document 99-049(1999年5月5日)3.2.5,p。 3-11(几何的SQL文本表示)。
[2]请参阅 PostGIS EWKB,EWKT和规范表单,PostGIS文档。4.1.2.
[3]请参阅 Howard Butler,Martin Daly,Allan Doyle,Tim Schaub和Christopher Schmidt,GeoJSON格式规范,修订版1.0(2008年6月16日)。
[4]请参阅ST_distance_sphere上的 PostGIS文档
[5]

请参阅MySQL参考手册中的 创建空间索引

For MyISAM tables, SPATIAL INDEX 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.
[6]有关详细信息,请参阅MySQL Spatial Limitations部分。