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 几何体 [2])和 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 独有的查找类型仅适用于空间字段。

“普通”字段(例如 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 字符串),rstGDALRaster 对象。

栅格查找

栅格查找语法类似于几何体的语法。唯一的区别是,可以将波段索引指定为附加输入。如果未指定波段索引,则默认使用第一个波段(索引 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 是几何输入,rstGDALRaster 对象。前两个查询中的波段索引默认为 0,其他查询中的波段索引设置为 1

虽然所有空间查找都可以在两侧使用栅格对象,但并非所有底层运算符都原生接受栅格输入。在运算符期望几何输入的情况下,栅格会自动转换为几何体。在解释查找结果时,务必牢记这一点。

所有查找中列出了栅格支持的类型,如 兼容性表 所示。涉及栅格的查找目前仅适用于 PostGIS 后端。

距离查询

简介

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

距离查找

可用性:PostGIS、MariaDB、MySQL、Oracle、SpatiaLite、PGRaster(原生)

提供以下距离查找

注意

对于测量(而不是根据距离查询),请使用 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 Raster (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

聚合函数

下表总结了每个空间后端可用的 GIS 特定聚合函数。 请注意,MariaDB 不支持任何这些聚合,因此已从表中排除。

聚合

PostGIS

Oracle

MySQL

SpatiaLite

Collect

X

X (≥ 8.0.24)

X

Extent

X

X

X

Extent3D

X

MakeLine

X

X

Union

X

X

X

脚注

返回顶部