# Django 6.0.7 ドキュメント

# GeoDjango データベース API

## 空間バックエンド (Spatial Backend)

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 固有のジオメトリで、16 進数の 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()

Note that this is equivalent to:

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

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.

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

Changed in Django 5.2.17:

In earlier versions, spatial lookups accepted `str` and `dict` types for new rasters, allowing file writes and network fetches.

### ジオメトリ・ルックアップ

地理情報クエリにおいて、ジオメトリを用いる一般的な形式は以下の通りです (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` オブジェクトです。バンドインデックスは最初の2つのクエリではデフォルトで `0` に設定され、他のクエリでは `1` に設定されます。

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

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

## 距離クエリ

### はじめに

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

### 距離ルックアップ

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

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

- `distance_lt`

- `distance_lte`

- `distance_gt`

- `distance_gte`

- `dwithin` (MariaDB and MySQL を除く)

注釈

距離をクエリするのではなく、 計測 する場合は `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 (3番目のバンド) がルックアップに使用されます。

## 互換表

### 空間のルックアップ (Spatial Lookup)

以下の表は、各空間データベースバックエンドで利用可能な空間ルックアップの概要です。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 (≥ 12.0.1) | 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
`geom_type` | X | X (≥ 23c) | X | X | X |
`intersects` | X | X | X | X | X | B
`isempty` | X |  |  |  | X |
`isvalid` | X | X | X (≥ 12.0.1) | X | X |
`num_dimensions` | 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 (≥ 12.0.1) | X | X (LWGEOM/RTTOPO)
`GeometryDistance` | X |  |  |  |
`GeometryType` | X | X (≥ 23c) | X | X | X
`Intersection` | X | X | X | X | X
`IsEmpty` | X |  |  |  | X
`IsValid` | X | X | X (≥ 12.0.1) | X | X
`Length` | X | X | X | X | X
`LineLocatePoint` | X |  |  |  | X
`MakeValid` | X |  |  |  | X (LWGEOM/RTTOPO)
`MemSize` | X |  |  |  |
`NumDimensions` | X |  |  |  | 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
`Rotate` | 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固有のアグリゲート関数の概要です。

集計関数 | PostGIS | Oracle | MariaDB | MySQL | SpatiaLite
--- | --- | --- | --- | --- | ---
`Collect` | X |  | X (≥ 12.0.1) | 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 (May 5, 1999), at Ch. 3.2.5, p. 3-11 (SQL Textual Representation of Geometry) 。

[2]

参照 PostGIS EWKB, EWKT and Canonical Forms, PostGIS documentation at Ch. 4.1.2.

[3]

参照 PostGIS documentation の `ST_DistanceSphere` を参照してください。

[4]

詳細は MySQL の空間データに関する制限 セクションを参照してください。