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 字串),而 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 的限制,可能必須以不同的方式表示具有地理座標系統中欄位的一些距離查詢。請參閱選取 SRID章節,以取得更多詳細資訊。
距離查找¶
可用性:PostGIS、MariaDB、MySQL、Oracle、SpatiaLite、PGRaster (原生)
提供以下距離查找
dwithin
(MariaDB 和 MySQL 除外)
注意
對於測量而不是查詢距離,請使用 Distance
函數。
距離查找採用包含以下內容的元組參數
用於計算的幾何圖形或柵格;以及
包含距離的數字或
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 |
---|---|---|---|---|---|---|
X |
X |
X |
X |
N |
||
X |
X |
X |
X |
N |
||
X |
X |
X |
X |
N |
||
X |
X |
X |
X |
X |
B |
|
X |
B |
|||||
X |
X |
X |
B |
|||
X |
X |
X |
B |
|||
X |
X |
X |
X |
C |
||
X |
X |
X |
X |
X |
B |
|
X |
X |
X |
X |
X |
N |
|
X |
X |
X |
X |
X |
N |
|
X |
X |
X |
X |
X |
N |
|
X |
X |
X |
X |
X |
N |
|
X |
X |
X |
B |
|||
X |
X |
X |
X |
X |
C |
|
X |
X |
X |
X |
X |
B |
|
X |
X |
X |
X |
X |
B |
|
X |
||||||
X |
X |
X |
X |
|||
X |
X |
X |
X |
X |
B |
|
X |
X |
X |
X |
C |
||
X |
X |
X |
X |
X |
B |
|
X |
X |
X |
X |
X |
B |
|
X |
X |
X |
X |
X |
B |
|
X |
C |
|||||
X |
C |
|||||
X |
B |
|||||
X |
B |
|||||
X |
C |
|||||
X |
C |
|||||
X |
C |
|||||
X |
C |
資料庫函數¶
下表概述了每個空間後端可用的特定於地理的資料庫函數。
函數 |
PostGIS |
Oracle |
MariaDB |
MySQL |
SpatiaLite |
---|---|---|---|---|---|
X |
X |
X |
X |
X |
|
X |
X |
X |
X |
X |
|
X |
X |
X |
|||
X |
X |
||||
X |
X |
||||
X |
X |
X |
X |
X |
|
X |
X |
X |
X |
X |
|
X |
X (LWGEOM/RTTOPO) |
||||
X |
X |
X (≥ 5.1) |
|||
X |
X |
X |
X |
X |
|
X |
X |
||||
X |
X |
X |
X |
X |
|
X |
X |
X |
X |
X |
|
X |
X |
X |
X |
X |
|
X |
X |
||||
X |
X |
X |
X |
X |
|
X |
X |
X |
X |
X |
|
X |
X |
X (LWGEOM/RTTOPO) |
|||
X |
X |
X |
X |
X |
|
X |
|||||
X |
X |
X |
X |
||
X |
X |
X |
X |
X |
|
X |
X |
||||
X |
X (LWGEOM/RTTOPO) |
||||
X |
|||||
X |
X |
X |
X |
X |
|
X |
X |
X |
X |
X |
|
X |
X |
X |
|||
X |
X |
X |
X |
||
X |
X |
X |
|||
X |
X |
||||
X |
X |
||||
X |
X |
X |
X |
X |
|
X |
X |
X |
|||
X |
X |
||||
X |
X |
X |
X |
X |
聚合函數¶
下表概述了每個空間後端可用的 GIS 特定聚合函數。請注意,MariaDB 不支援任何這些聚合,因此不包括在表中。
聚合 |
PostGIS |
Oracle |
MySQL |
SpatiaLite |
---|---|---|---|---|
X |
X (≥ 8.0.24) |
X |
||
X |
X |
X |
||
X |
||||
X |
X |
|||
X |
X |
X |
註腳