GeoDjango データベース APILink to this heading

空間バックエンド (Spatial Backend)Link to this heading

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 の空間データに関する制限Link to this heading

Django は、最近の MySQL バージョンで利用可能な、実際のジオメトリを操作する空間関数をサポートしています。しかし、空間関数は PostGIS のような他のバックエンドほど豊富ではありません。

ラスターのサポートLink to this heading

RasterField は現在、PostGIS バックエンドのみに実装されています。ラスターフィールドに対する空間ルックアップは可能ですが、空間データベース関数や集計は実装されていません。

モデルを作成し、ジオメトリフィールドを保存するLink to this heading

以下にジオメトリオブジェクトの作成例を示します (Zipcode モデルを想定):

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

GEOSGeometry オブジェクトもジオメトリモデルを保存するために使用できます:

Python console
>>> 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 に暗黙的に変換されます:

Python console
>>> 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 固有のジオメトリで、16 進数の WKB ジオメトリ [2]) 、GeoJSON (RFC 7946 参照) を使用して渡すことができます。基本的に、入力が GEOSGeometry オブジェクトでない場合、ジオメトリフィールドは入力から GEOSGeometry インスタンスを作成しようとします。

GEOSGeometry オブジェクトを作成する詳細については、GEOS チュートリアル を参照してください。

ラスターフィールドを持つモデルの作成と保存Link to this heading

ラスターモデルを作成するとき、ラスターフィールドは、遅延評価を使用して、入力を GDALRaster に暗黙的に変換します。そのため、ラスタフィールドは GDALRaster コンストラクタが受け付けるすべての入力を受け入れます。

以下は、ラスターファイル volcano.tif からラスターオブジェクトを作成する方法の例です (Elevation モデルを想定) :

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

GDALRaster オブジェクトもラスターモデルの保存に使用できます:

Python console
>>> 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()

これは次と等価です:

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

空間のルックアップ (Spatial Lookup)Link to this heading

GeoDjango のルックアップ型は filter()exclude() などの manager メソッドで使うことができます。しかし、 GeoDjango 固有のルックアップ型は空間フィールドでのみ利用可能です。

Filters on 'normal' fields (e.g. CharField) may be chained with those on geographic fields. Geographic lookups accept geometry and raster input on both sides, and input types can be mixed freely in most cases. However, unlike assignments to model fields, with lookups, types such as str, pathlib.Path, and dict must be wrapped by GDALRaster to signify that the potential for file writing or network fetching is acceptable. For the rationale, see raster security considerations.

地理情報ルックアップの一般的な構造を以下に記載します。完全なリファレンスは、 空間ルックアップのリファレンス にあります。

ジオメトリ・ルックアップLink to this heading

地理情報クエリにおいて、ジオメトリを用いる一般的な形式は以下の通りです (GeoDjango モデル API で使用されている Zipcode モデルを想定):

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

例:

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

この場合、 poly は地理情報フィールド、 contains は空間ルックアップタイプ、 pnt はパラメータ (GEOSGeometry オブジェクト、または GeoJSON、WKT、HEXEWKB の文字列)、そして rstGDALRaster オブジェクトです。

ラスター・ルックアップLink to this heading

ラスタールックアップの構文はジオメトリの構文に似ています。唯一の違いは、バンドインデックスを追加入力として指定できることです。バンドインデックスが指定されていない場合は、デフォルトで最初のバンドが使用されます (インデックス"0") 。その場合、構文はジオメトリルックアップの構文と同一です。

バンドインデックスを指定するには、ルックアップに追加のパラメータを両側で指定できます。左側では、バンドインデックスを渡すためにダブルアンダースコア構文が使用されます。右側では、ラスターとバンドのインデックスのタプルを指定できます。

これにより、ラスターを使用するルックアップの一般的な形式が得られます (GeoDjango モデル API で使用されている Elevation モデルを想定):

Text
>>> 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>)

例:

Python console
>>> 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 オブジェクトです。バンドインデックスは最初の2つのクエリではデフォルトで 0 に設定され、他のクエリでは 1 に設定されます。

すべての空間ルックアップはラスターオブジェクトの両側で使用できますが、すべての基本演算子がラスター入力をネイティブに受け付けるわけではありません。演算子がジオメトリ入力を想定している場合、ラスタは自動的にジオメトリに変換されます。ルックアップ結果を解釈する際には、この点に留意することが重要です。

ラスターをサポートするタイプは 互換表 のすべてのルックアップにリストされています。ラスタを含むルックアップは現在のところ PostGIS バックエンドでのみ利用可能です。

距離クエリLink to this heading

はじめにLink to this heading

残念ながら、地球は平らではないため、空間データでの距離計算は厄介です。PostGIS の制限により、地理座標系のフィールドを使用した距離のクエリは、別の方法で表現しなければならない場合があります。詳細は GeoDjango モデル API ドキュメントの SRID の選択 セクションを参照してください。

距離ルックアップLink to this heading

利用可能なDB: PostGIS、MariaDB、MySQL、Oracle、SpatiaLite、PGRaster (ネイティブ)

以下の距離ルックアップが利用できます:

距離ルックアップは、次のように構成されるタプルパラメータを受け取ります:

  1. 計算のベースとなるジオメトリまたはラスター。

  2. 距離を含む数字または Distance オブジェクト。

Distance オブジェクトが使用されている場合、任意の単位で表現される可能性があります(SQL 生成時には、フィールドの単位に変換された単位が使用される)。それ以外の場合、数値パラメータはフィールドの単位であると想定されます。

例えば、SouthTexasCity というモデル (GeoDjango 距離テスト から) が、テキサス州南部の都市に有効な 投影 座標系にあるとします:

Code
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)

距離クエリは次のように実行できます:

Python console
>>> 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値のタプルをルックアップに渡すことができます:

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

ラスター rst のバンドのうち、インデックス2 (3番目のバンド) がルックアップに使用されます。

互換表Link to this heading

空間のルックアップ (Spatial Lookup)Link to this heading

以下の表は、各空間データベースバックエンドで利用可能な空間ルックアップの概要です。PostGIS Raster (PGRaster) のルックアップは ラスタールックアップの詳細 に記載されている3つのカテゴリに分類されます: ネイティブサポート 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

X

B

covers

X

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

データベース関数Link to this heading

次の表は、各空間バックエンドで使用できるジオグラフィ固有のデータベース関数の概要です。

関数

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)

GeometryDistance

X

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

集計関数Link to this heading

以下の表は、各空間バックエンドで利用可能な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

脚注