GeoDjango 数据库 API

空间后端

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 的空间限制

Django 支持在现代 MySQL 版本中操作真实几何图形的空间函数。然而,与其他后端如 PostGIS 相比,空间函数并不那么丰富。

栅格支持

RasterField 目前仅在 PostGIS 后端中实现。对于栅格字段,可以使用空间查找,但尚未为栅格字段实现空间数据库函数和聚合函数。

创建和保存具有几何字段的模型

以下是如何创建一个几何对象的示例(假设有 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(Well Known Text [1])、HEXEWKB(PostGIS 特定的十六进制 WKB 几何图形[#fnewkb]_)和 GeoJSON(参见 RFC 7946)传递几何参数。基本上,如果输入不是 GEOSGeometry 对象,几何字段将尝试从输入创建一个 GEOSGeometry 实例。

有关创建 GEOSGeometry 对象的更多信息,请参考 GEOS 教程

使用栅格字段创建和保存模型

创建栅格模型时,栅格字段将使用延迟计算将输入隐式转换为 GDALRaster。因此,栅格字段将接受任何被 GDALRaster 构造函数接受的输入。

以下是如何从栅格文件 volcano.tif 创建一个栅格对象的示例(假设有 Elevation 模型):

>>> from elevation.models import Elevation
>>> dem = Elevation(name="Volcano", rast="/path/to/raster/volcano.tif")
>>> dem.save()

GDALRaster 对象也可以用于保存栅格模型:

>>> from django.contrib.gis.gdal import GDALRaster
>>> rast = GDALRaster(
...     {
...         "width": 10,
...         "height": 10,
...         "name": "Canyon",
...         "srid": 4326,
...         "scale": [0.1, -0.1],
...         "bands": [{"data": range(100)}],
...     }
... )
>>> dem = Elevation(name="Canyon", rast=rast)
>>> dem.save()

请注意,这相当于:

>>> dem = Elevation.objects.create(
...     name="Canyon",
...     rast={
...         "width": 10,
...         "height": 10,
...         "name": "Canyon",
...         "srid": 4326,
...         "scale": [0.1, -0.1],
...         "bands": [{"data": range(100)}],
...     },
... )

空间查找

GeoDjango 的查找类型可以与任何管理器方法一起使用,如 filter()exclude() 等。然而,独特于 GeoDjango 的查找类型仅在空间字段上可用。

对于 'normal' 字段(例如 CharField)的过滤器可以与地理字段的过滤器链式连接。地理查找接受两侧的几何和栅格输入,并且输入类型可以自由混合使用。

地理查找的一般结构如下所述。完整的参考信息可以在 空间查找参考 中找到。

空间查找

使用几何图形的地理查询通常采用以下一般形式(假设在 GeoDjango 模型 API 中使用了 Zipcode 模型):

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

例如:

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

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

栅格查找

栅格查找的语法与几何图形的语法类似。唯一的区别是可以指定一个带索引作为附加输入。如果未指定带索引,则默认使用第一个带(索引 0)。在这种情况下,语法与几何查找的语法相同。

要指定带索引,可以在查找的两侧指定附加参数。在左侧,使用双下划线语法传递带索引。在右侧,可以指定栅格和带索引的元组。

这导致了涉及栅格的查找的以下一般形式(假设在 GeoDjango 模型 API 中使用了 Elevation 模型):

>>> qs = Elevation.objects.filter(<field>__<lookup_type>=<parameter>)
>>> qs = Elevation.objects.filter(<field>__<band_index>__<lookup_type>=<parameter>)
>>> qs = Elevation.objects.filter(<field>__<lookup_type>=(<raster_input, <band_index>)

例如:

>>> qs = Elevation.objects.filter(rast__contains=geom)
>>> qs = Elevation.objects.filter(rast__contains=rst)
>>> qs = Elevation.objects.filter(rast__1__contains=geom)
>>> qs = Elevation.objects.filter(rast__contains=(rst, 1))
>>> qs = Elevation.objects.filter(rast__1__contains=(rst, 1))

在示例的左侧,rast 是地理栅格字段,contains 是空间查找类型。在右侧,geom 是一个几何输入,rst 是一个 GDALRaster 对象。带索引在前两个查询中默认为 0,在其他查询中设置为 1

虽然所有空间查找都可以在两侧使用栅格对象,但并不是所有底层运算符本身都能接受栅格输入。对于期望几何输入的运算符,栅格会自动转换为几何图形。在解释查找结果时,需要牢记这一点。

有关所有查找的栅格支持类型,请参阅 兼容性表。涉及栅格的查找目前仅适用于 PostGIS 后端。

距离查询

介绍

使用空间数据进行距离计算很棘手,因为不幸的是,地球不是平的。由于 PostGIS 的限制,一些在地理坐标系统中的距离查询可能必须以不同的方式表示。有关更多详细信息,请参阅 GeoDjango 模型 API 文档中的 选择一个 SRID 部分。

距离查找

可用性 :PostGIS, MariaDB, MySQL, Oracle, SpatiaLite, PGRaster (Native)

以下是可用的距离查找:

备注

对于 测量,而不是查询距离,使用 Distance 函数。

距离查找需要一个元组参数,包括:

  1. 用于计算的几何体或栅格;和
  2. 一个数字或 Distance 对象,包含距离。

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

备注

在 PostGIS 中,ST_Distance_Sphere 限制地理距离查询所使用的几何类型。[3] 然而,这些查询可能会花费很长时间,因为必须为查询中的 一行动态计算大圆距离。这是因为传统几何字段上的空间索引无法使用。

为了在 WGS84 距离查询中获得更好的性能,考虑在数据库中使用 地理列,因为它们能够在距离查询中使用它们的空间索引。您可以通过在字段定义中设置 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)

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

>>> from django.contrib.gis.geos import GEOSGeometry
>>> from django.contrib.gis.measure import D  # ``D`` is a shortcut for ``Distance``
>>> from geoapp.models import SouthTexasCity
# Distances will be calculated from this point, which does not have to be projected.
>>> pnt = GEOSGeometry("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)))

栅格查询的工作方式相同,只需将几何字段 point 替换为栅格字段,或将 pnt 对象替换为栅格对象,或两者都替换。要在右侧指定栅格输入的带索引,可以将一个 3-元组传递给查找,如下所示:

>>> qs = SouthTexasCity.objects.filter(point__distance_gte=(rst, 2, D(km=7)))

将使用栅格 rst 的带索引为 2(第三个带)进行查找。

兼容性表

空间查找

以下表格提供了每个空间数据库后端可用的空间查找的摘要。PostGIS 栅格(PGRaster)查找分为三个类别,如 栅格查找详细信息 中所述:本机支持 N、双边本机支持 B 和几何转换支持 C

查找类型 PostGIS Oracle MariaDB MySQL [4] SpatiaLite PGRaster
bbcontains X   X X X N
bboverlaps X   X X X N
contained X   X X X N
contains X X X X X B
contains_properly X         B
coveredby X X     X B
covers X X     X B
crosses X   X X X C
disjoint X X X X X B
distance_gt X X X X X N
distance_gte X X X X X N
distance_lt X X X X X N
distance_lte X X X X X N
dwithin X X     X B
equals X X X X X C
exact X X X X X B
intersects X X X X X B
isempty X          
isvalid X X   X X  
overlaps X X X X X B
relate X X X   X C
same_as X X X X X B
touches X X X X X B
within X X X X X B
left X         C
right X         C
overlaps_left X         B
overlaps_right X         B
overlaps_above X         C
overlaps_below X         C
strictly_above X         C
strictly_below X         C

数据库函数

以下表格提供了每个空间后端可用的地理专用数据库函数的摘要。

函数 PostGIS Oracle MariaDB MySQL SpatiaLite
Area X X X X X
AsGeoJSON X X X X X
AsGML X X     X
AsKML X       X
AsSVG X       X
AsWKB X X X X X
AsWKT X X X X X
Azimuth X       X (LWGEOM/RTTOPO)
BoundingCircle X X     X (≥ 5.1)
Centroid X X X X X
ClosestPoint X       X
Difference X X X X X
Distance X X X X X
Envelope X X X X X
ForcePolygonCW X       X
FromWKB X X X X X
FromWKT X X X X X
GeoHash X     X X (LWGEOM/RTTOPO)
Intersection X X X X X
IsEmpty X        
IsValid X X   X X
Length X X X X X
LineLocatePoint X       X
MakeValid X       X (LWGEOM/RTTOPO)
MemSize X        
NumGeometries X X X X X
NumPoints X X X X X
Perimeter X X     X
PointOnSurface X X X   X
Reverse X X     X
Scale X       X
SnapToGrid X       X
SymDifference X X X X X
Transform X X     X
Translate X       X
Union X X X X X

聚合函数

The following table provides a summary of what GIS-specific aggregate functions are available on each spatial backend. Please note that MariaDB does not support any of these aggregates, and is thus excluded from the table.

聚合 PostGIS Oracle MySQL SpatiaLite
Collect X   X (≥ 8.0.24) X
Extent X X   X
Extent3D X      
MakeLine X     X
Union X X   X

脚注

[1]请参阅 Open Geospatial Consortium, Inc. 的 OpenGIS Simple Feature Specification For SQL,文件编号 99-049(1999 年 5 月 5 日),第 3.2.5 章,第 3-11 页(几何图形的 SQL 文本表示)。
[2]请参阅 PostGIS EWKB、EWKT 和规范形式,PostGIS 文档第 4.1.2 章。
[3]请参阅 PostGIS 文档 中关于 ST_DistanceSphere 的部分。
[4]详情请参考 MySQL 的空间限制 部分。
Back to Top