---
title: "GeoDjango チュートリアル"
version: 6.0
locale: ja
source: https://docs.djangoproject.com/ja/6.0/ref/contrib/gis/tutorial/
canonical: https://djangodocs.dev/ja/6.0/ref/contrib/gis/tutorial/
---
# GeoDjango チュートリアル

## はじめに

GeoDjangoは、Django用の標準のcontribモジュールであり、それを世界クラスの地理情報Webフレームワークに変えます。GeoDjangoは、位置情報サービスなどの地理情報Webアプリケーションを作成するのを可能な限り簡単にすることを目指しています。その特徴は次のとおりです:

- [OGC](https://www.ogc.org/) ジオメトリとラスターデータ用のDjangoモデルフィールド。
- 空間データのクエリと操作のための Django の ORM の拡張機能。
- GISジオメトリとラスタの操作、およびさまざまな形式のデータ操作のための、疎結合の高レベルPythonインターフェース。
- admin アプリケーションからジオメトリフィールドを編集する

このチュートリアルは Django に慣れていることを前提にしています。従って、 Django が初めての方は、まず [通常のチュートリアル](/ja/6.0/intro/tutorial01/) を読んで Django に慣れてください。

> **Note**
>
> GeoDjango has additional requirements beyond what Django requires -- please
> consult the [installation documentation](/ja/6.0/ref/contrib/gis/install/) for more details.

このチュートリアルでは、地理情報を表示するためのウェブアプリケーションの作成方法を説明します。このチュートリアルでは、[world borders](https://web.archive.org/web/20240123190237/https://thematicmapping.org/downloads/world_borders.php) [^1] を表示します。このチュートリアルで使用されるコードの一部は、[GeoDjango basic apps](https://code.google.com/archive/p/geodjango-basic-apps) プロジェクトから取得されたか、その影響を受けています。 [^2]

> **Note**
>
> チュートリアルの各セクションを順を追って進んでください。

## セットアップ

### 空間データベースを作成する

通常、特別な設定は必要ないので、他のプロジェクトと同じようにデータベースを作成できます。選択したデータベースについて、いくつかのヒントを提供します:

- [PostGIS のインストール](/ja/6.0/ref/contrib/gis/install/postgis/)
- [SpatiaLite のインストール](/ja/6.0/ref/contrib/gis/install/spatialite/)

### 新しいプロジェクトを作成する

標準の `django-admin` スクリプトを使って、 `geodjango` というプロジェクトを作成します:

```console
$ django-admin startproject geodjango
```

*Windows*

```doscon
...\> django-admin startproject geodjango
```

これで新しいプロジェクトが初期化されます。ここで、 `geodjango` プロジェクトの中に `world` Django アプリケーションを作成します:

```console
$ cd geodjango
$ python manage.py startapp world
```

*Windows*

```doscon
...\> cd geodjango
...\> py manage.py startapp world
```

### `settings.py` の設定

`geodjango` プロジェクトの設定は `geodjango/settings.py` ファイルに保存されています。データベース接続設定を編集して、自分の環境に合わせてください:

```
DATABASES = {
    "default": {
        "ENGINE": "django.contrib.gis.db.backends.postgis",
        "NAME": "geodjango",
        "USER": "geo",
    },
}
```

さらに、 [`INSTALLED_APPS`](/ja/6.0/ref/settings/#std-setting-INSTALLED_APPS) 設定を変更して、 [`django.contrib.admin`](/ja/6.0/ref/contrib/admin/#module-django.contrib.admin), [`django.contrib.gis`](/ja/6.0/ref/contrib/gis/#module-django.contrib.gis), `world` (新しく作成したアプリケーション) を含めるようにします:

```
INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "django.contrib.gis",
    "world",
]
```

## 地理データ

### 世界の国境

The world borders data is available in this [zip file](https://web.archive.org/web/20231220150759/https://thematicmapping.org/downloads/TM_WORLD_BORDERS-0.3.zip). Create a `data`
directory in the `world` application, download the world borders data, and
unzip. On GNU/Linux platforms, use the following commands:

```console
$ mkdir world/data
$ cd world/data
$ wget https://web.archive.org/web/20231220150759/https://thematicmapping.org/downloads/TM_WORLD_BORDERS-0.3.zip
$ unzip TM_WORLD_BORDERS-0.3.zip
$ cd ../..
```

*Windows*

```doscon
...\> mkdir world\data
...\> cd world\data
...\> wget https://web.archive.org/web/20231220150759/https://thematicmapping.org/downloads/TM_WORLD_BORDERS-0.3.zip
...\> unzip TM_WORLD_BORDERS-0.3.zip
...\> cd ..\..
```

The world borders ZIP file contains a set of data files collectively known as
an [ESRI Shapefile](https://en.wikipedia.org/wiki/Shapefile), one of the most popular geospatial data formats. When
unzipped, the world borders dataset includes files with the following
extensions:

- `.shp`: 世界の国境のジオメトリのベクトルデータを保持します。
- `.shx`: `.shp` に保存されているジオメトリのための空間インデックスファイル。
- `.dbf`: 整数や文字列フィールドなどの非ジオメトリ属性データを保持するデータベースファイル。
- `.prj`: シェープファイルに格納されている地理データの空間参照情報が含まれています。

### `ogrinfo` を使って空間データを調べる

GDAL の `ogrinfo` ユーティリティを使うと、シェープファイルやその他のベクトルデータソースのメタデータを調べることができます:

```console
$ ogrinfo world/data/TM_WORLD_BORDERS-0.3.shp
INFO: Open of `world/data/TM_WORLD_BORDERS-0.3.shp'
      using driver `ESRI Shapefile' successful.
1: TM_WORLD_BORDERS-0.3 (Polygon)
```

*Windows*

```doscon
...\> ogrinfo world\data\TM_WORLD_BORDERS-0.3.shp
INFO: Open of `world/data/TM_WORLD_BORDERS-0.3.shp'
      using driver `ESRI Shapefile' successful.
1: TM_WORLD_BORDERS-0.3 (Polygon)
```

`ogrinfo` tells us that the shapefile has one layer, and that this
layer contains polygon data. To find out more, we'll specify the layer name
and use the `-so` option to get only the important summary information:

```console
$ ogrinfo -so world/data/TM_WORLD_BORDERS-0.3.shp TM_WORLD_BORDERS-0.3
INFO: Open of `world/data/TM_WORLD_BORDERS-0.3.shp'
      using driver `ESRI Shapefile' successful.

Layer name: TM_WORLD_BORDERS-0.3
Metadata:
  DBF_DATE_LAST_UPDATE=2008-07-30
Geometry: Polygon
Feature Count: 246
Extent: (-180.000000, -90.000000) - (180.000000, 83.623596)
Layer SRS WKT:
GEOGCRS["WGS 84",
    DATUM["World Geodetic System 1984",
        ELLIPSOID["WGS 84",6378137,298.257223563,
            LENGTHUNIT["metre",1]]],
    PRIMEM["Greenwich",0,
        ANGLEUNIT["degree",0.0174532925199433]],
    CS[ellipsoidal,2],
        AXIS["latitude",north,
            ORDER[1],
            ANGLEUNIT["degree",0.0174532925199433]],
        AXIS["longitude",east,
            ORDER[2],
            ANGLEUNIT["degree",0.0174532925199433]],
    ID["EPSG",4326]]
Data axis to CRS axis mapping: 2,1
FIPS: String (2.0)
ISO2: String (2.0)
ISO3: String (3.0)
UN: Integer (3.0)
NAME: String (50.0)
AREA: Integer (7.0)
POP2005: Integer64 (10.0)
REGION: Integer (3.0)
SUBREGION: Integer (3.0)
LON: Real (8.3)
LAT: Real (7.3)
```

*Windows*

```doscon
...\> ogrinfo -so world\data\TM_WORLD_BORDERS-0.3.shp TM_WORLD_BORDERS-0.3
INFO: Open of `world/data/TM_WORLD_BORDERS-0.3.shp'
      using driver `ESRI Shapefile' successful.

Layer name: TM_WORLD_BORDERS-0.3
Metadata:
  DBF_DATE_LAST_UPDATE=2008-07-30
Geometry: Polygon
Feature Count: 246
Extent: (-180.000000, -90.000000) - (180.000000, 83.623596)
Layer SRS WKT:
GEOGCRS["WGS 84",
    DATUM["World Geodetic System 1984",
        ELLIPSOID["WGS 84",6378137,298.257223563,
            LENGTHUNIT["metre",1]]],
    PRIMEM["Greenwich",0,
        ANGLEUNIT["degree",0.0174532925199433]],
    CS[ellipsoidal,2],
        AXIS["latitude",north,
            ORDER[1],
            ANGLEUNIT["degree",0.0174532925199433]],
        AXIS["longitude",east,
            ORDER[2],
            ANGLEUNIT["degree",0.0174532925199433]],
    ID["EPSG",4326]]
Data axis to CRS axis mapping: 2,1
FIPS: String (2.0)
ISO2: String (2.0)
ISO3: String (3.0)
UN: Integer (3.0)
NAME: String (50.0)
AREA: Integer (7.0)
POP2005: Integer64 (10.0)
REGION: Integer (3.0)
SUBREGION: Integer (3.0)
LON: Real (8.3)
LAT: Real (7.3)
```

This detailed summary information tells us the number of features in the layer
(246), the geographic bounds of the data, the spatial reference system
("SRS WKT"), as well as type information for each attribute field. For example,
`FIPS: String (2.0)` indicates that the `FIPS` character field has
a maximum length of 2. Similarly, `LON: Real (8.3)` is a floating-point
field that holds a maximum of 8 digits up to three decimal places.

## 地理情報モデル

### 地理情報モデルを定義する

さて、 `ogrinfo` を使ってデータセットを調べたので、このデータを表す GeoDjango モデルを作成しましょう:

```
from django.contrib.gis.db import models

class WorldBorder(models.Model):
    # Regular Django fields corresponding to the attributes in the
    # world borders shapefile.
    name = models.CharField(max_length=50)
    area = models.IntegerField()
    pop2005 = models.IntegerField("Population 2005")
    fips = models.CharField("FIPS Code", max_length=2, null=True)
    iso2 = models.CharField("2 Digit ISO", max_length=2)
    iso3 = models.CharField("3 Digit ISO", max_length=3)
    un = models.IntegerField("United Nations Code")
    region = models.IntegerField("Region Code")
    subregion = models.IntegerField("Sub-Region Code")
    lon = models.FloatField()
    lat = models.FloatField()

    # GeoDjango-specific: a geometry field (MultiPolygonField)
    mpoly = models.MultiPolygonField()

    # Returns the string representation of the model.
    def __str__(self):
        return self.name
```

`models` モジュールが `django.contrib.gis.db` からインポートされていることに注意してください。

The default spatial reference system for geometry fields is WGS84 (meaning
the [SRID](https://en.wikipedia.org/wiki/SRID) is 4326) -- in other words, the field coordinates are in
longitude, latitude pairs in units of degrees. To use a different
coordinate system, set the SRID of the geometry field with the `srid`
argument. Use an integer representing the coordinate system's EPSG code.

### `migrate` を実行する

モデルを定義した後、データベースと同期する必要があります。まず、データベースマイグレーションを作成してください:

```console
$ python manage.py makemigrations
Migrations for 'world':
  world/migrations/0001_initial.py:
    + Create model WorldBorder
```

*Windows*

```doscon
...\> py manage.py makemigrations
Migrations for 'world':
  world/migrations/0001_initial.py:
    + Create model WorldBorder
```

`WorldBorder` モデルのテーブルを生成するSQLを見てみましょう:

```console
$ python manage.py sqlmigrate world 0001
```

*Windows*

```doscon
...\> py manage.py sqlmigrate world 0001
```

このコマンドを実行すると、次の出力が生成されるはずです:

```sql
BEGIN;
--
-- Create model WorldBorder
--
CREATE TABLE "world_worldborder" (
    "id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
    "name" varchar(50) NOT NULL,
    "area" integer NOT NULL,
    "pop2005" integer NOT NULL,
    "fips" varchar(2) NOT NULL,
    "iso2" varchar(2) NOT NULL,
    "iso3" varchar(3) NOT NULL,
    "un" integer NOT NULL,
    "region" integer NOT NULL,
    "subregion" integer NOT NULL,
    "lon" double precision NOT NULL,
    "lat" double precision NOT NULL
    "mpoly" geometry(MULTIPOLYGON,4326) NOT NULL
)
;
CREATE INDEX "world_worldborder_mpoly_id" ON "world_worldborder" USING GIST ("mpoly");
COMMIT;
```

これが正しければ、 [`migrate`](/ja/6.0/ref/django-admin/#django-admin-migrate) を実行して、このテーブルをデータベースに作成してください。

```console
$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions, world
Running migrations:
  ...
  Applying world.0001_initial... OK
```

*Windows*

```doscon
...\> py manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions, world
Running migrations:
  ...
  Applying world.0001_initial... OK
```

## 空間データをインポートする

This section will show you how to import the world borders shapefile into the
database via GeoDjango models using the [LayerMapping データインポートユーティリティ](/ja/6.0/ref/contrib/gis/layermapping/).

空間データベースにデータをインポートする方法は色々あります。GeoDjango に含まれるツール以外にも、以下のような方法があります:

- [ogr2ogr](https://gdal.org/programs/ogr2ogr.html) は、GDAL に含まれるコマンドラインユーティリティであり、多くのベクトルデータ形式を PostGIS、MySQL、および Oracle データベースにインポートできます。
- [shp2pgsql](https://postgis.net/docs/using_postgis_dbmanagement.html#shp2pgsql_usage): このユーティリティはPostGISに含まれ、ESRI shapefileをPostGISにインポートします。

### GDAL インターフェース

Earlier, you used `ogrinfo` to examine the contents of the world borders
shapefile. GeoDjango also includes a Pythonic interface to GDAL's powerful OGR
library that can work with all the vector data sources that OGR supports.

まず、Django シェルを起動します:

```console
$ python manage.py shell
```

*Windows*

```doscon
...\> py manage.py shell
```

チュートリアルの最初の方で [世界の国境](#worldborders) データをダウンロードしている場合は、Pythonの [`pathlib.Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path) を使用してそのパスを指定できます:

```pycon
>>> from pathlib import Path
>>> import world
>>> world_shp = Path(world.__file__).resolve().parent / "data" / "TM_WORLD_BORDERS-0.3.shp"
```

ここで、GeoDjango の [`DataSource`](/ja/6.0/ref/contrib/gis/gdal/#django.contrib.gis.gdal.DataSource) インタフェースを使って、 world borders shapefile を開いてください:

```pycon
>>> from django.contrib.gis.gdal import DataSource
>>> ds = DataSource(world_shp)
>>> print(ds)
/ ... /geodjango/world/data/TM_WORLD_BORDERS-0.3.shp (ESRI Shapefile)
```

データソースオブジェクトは異なるレイヤーの地理空間フィーチャを持つことができます。しかし、シェープファイルは 1 つのレイヤーしか持つことができません:

```pycon
>>> print(len(ds))
1
>>> lyr = ds[0]
>>> print(lyr)
TM_WORLD_BORDERS-0.3
```

レイヤーのジオメトリタイプと、含まれているフィーチャの数を確認できます:

```pycon
>>> print(lyr.geom_type)
Polygon
>>> print(len(lyr))
246
```

> **Note**
>
> Unfortunately, the shapefile data format does not allow for greater
> specificity with regards to geometry types. This shapefile, like many
> others, actually includes `MultiPolygon` geometries, not Polygons. It's
> important to use a more general field type in models: a GeoDjango
> `MultiPolygonField` will accept a `Polygon` geometry, but a
> `PolygonField` will not accept a `MultiPolygon` type geometry. This is
> why the `WorldBorder` model defined above uses a `MultiPolygonField`.

The [`Layer`](/ja/6.0/ref/contrib/gis/gdal/#django.contrib.gis.gdal.Layer) may also have a spatial reference
system associated with it. If it does, the `srs` attribute will return a
[`SpatialReference`](/ja/6.0/ref/contrib/gis/gdal/#django.contrib.gis.gdal.SpatialReference) object:

```pycon
>>> srs = lyr.srs
>>> print(srs)
GEOGCS["WGS 84",
DATUM["WGS_1984",
    SPHEROID["WGS 84",6378137,298.257223563,
        AUTHORITY["EPSG","7030"]],
    AUTHORITY["EPSG","6326"]],
PRIMEM["Greenwich",0,
    AUTHORITY["EPSG","8901"]],
UNIT["degree",0.0174532925199433,
    AUTHORITY["EPSG","9122"]],
AXIS["Latitude",NORTH],
AXIS["Longitude",EAST],
AUTHORITY["EPSG","4326"]]
>>> srs.proj  # PROJ representation
'+proj=longlat +datum=WGS84 +no_defs'
```

このシェープファイルは一般的なWGS84空間参照システム、つまりデータは度の単位で経度緯度の組を使用しています。

In addition, shapefiles also support attribute fields that may contain
additional data. Here are the fields on the World Borders layer:

```pycon
>>> print(lyr.fields)
['FIPS', 'ISO2', 'ISO3', 'UN', 'NAME', 'AREA', 'POP2005', 'REGION', 'SUBREGION', 'LON', 'LAT']
```

以下のコードで、各フィールドに関連するOGRタイプ (整数や文字列など) を調べることができます:

```pycon
>>> [fld.__name__ for fld in lyr.field_types]
['OFTString', 'OFTString', 'OFTString', 'OFTInteger', 'OFTString', 'OFTInteger', 'OFTInteger64', 'OFTInteger', 'OFTInteger', 'OFTReal', 'OFTReal']
```

レイヤー内の各フィーチャをイテレートし、フィーチャのジオメトリ (`geom` 属性でアクセス) とフィーチャの属性フィールド (`get()` メソッドで **値** にアクセス) の両方から情報を抽出できます:

```pycon
>>> for feat in lyr:
...     print(feat.get("NAME"), feat.geom.num_points)
...
Guernsey 18
Jersey 26
South Georgia South Sandwich Islands 338
Taiwan 363
```

[`Layer`](/ja/6.0/ref/contrib/gis/gdal/#django.contrib.gis.gdal.Layer) オブジェクトはスライス可能です。

```pycon
>>> lyr[0:2]
[<django.contrib.gis.gdal.feature.Feature object at 0x2f47690>, <django.contrib.gis.gdal.feature.Feature object at 0x2f47650>]
```

また、個々のフィーチャは、フィーチャ ID で検索できます:

```pycon
>>> feat = lyr[234]
>>> print(feat.get("NAME"))
San Marino
```

国境ジオメトリは、WKT および GeoJSON としてエクスポートできます:

```pycon
>>> geom = feat.geom
>>> print(geom.wkt)
POLYGON ((12.415798 43.957954,12.450554 ...
>>> print(geom.json)
{ "type": "Polygon", "coordinates": [ [ [ 12.415798, 43.957954 ], [ 12.450554, 43.979721 ], ...
```

### `LayerMapping`

データをインポートするには、Pythonスクリプト内で `LayerMapping` を使用します。次のコードを含む `world` アプリケーション内に `load.py` というファイルを作成してください:

```
from pathlib import Path
from django.contrib.gis.utils import LayerMapping
from .models import WorldBorder

world_mapping = {
    "fips": "FIPS",
    "iso2": "ISO2",
    "iso3": "ISO3",
    "un": "UN",
    "name": "NAME",
    "area": "AREA",
    "pop2005": "POP2005",
    "region": "REGION",
    "subregion": "SUBREGION",
    "lon": "LON",
    "lat": "LAT",
    "mpoly": "MULTIPOLYGON",
}

world_shp = Path(__file__).resolve().parent / "data" / "TM_WORLD_BORDERS-0.3.shp"

def run(verbose=True):
    lm = LayerMapping(WorldBorder, world_shp, world_mapping, transform=False)
    lm.save(strict=True, verbose=verbose)
```

何が起こっているかについての、ちょっとしたノート:

- Each key in the `world_mapping` dictionary corresponds to a field in the
  `WorldBorder` model. The value is the name of the shapefile field
  that data will be loaded from.
- The key `mpoly` for the geometry field is `MULTIPOLYGON`, the
  geometry type GeoDjango will import the field as. Even simple polygons in
  the shapefile will automatically be converted into collections prior to
  insertion into the database.
- シェープファイルへのパスは絶対パスではないことに注意してください。つまり、 `world` アプリケーション ( `data` サブディレクトリを含む) を別の場所に移動しても、スクリプトは動作します。
- `transform` キーワードは `False` に設定されています。なぜなら、shapefile のデータは変換する必要がないためです。これはすでに WGS84 (SRID=4326) であるからです。

その後、`geodjango` プロジェクトディレクトリから Django シェルを呼び出してください。

```console
$ python manage.py shell
```

*Windows*

```doscon
...\> py manage.py shell
```

次に、`load` モジュールをインポートし、 `run` ルーチンを呼び出して、 `LayerMapping` が作業を行う様子を見てください:

```pycon
>>> from world import load
>>> load.run()
```

### `ogrinspect` を試す

Now that you've seen how to define geographic models and import data with the
[LayerMapping データインポートユーティリティ](/ja/6.0/ref/contrib/gis/layermapping/), it's possible to further automate this
process with use of the [`ogrinspect`](/ja/6.0/ref/contrib/gis/commands/#django-admin-ogrinspect) management command. The
[`ogrinspect`](/ja/6.0/ref/contrib/gis/commands/#django-admin-ogrinspect) command  introspects a GDAL-supported vector data source
(e.g., a shapefile) and generates a model definition and `LayerMapping`
dictionary automatically.

コマンドの一般的な使用法は以下の通りです:

```console
$ python manage.py ogrinspect [options] <data_source> <model_name> [options]
```

*Windows*

```doscon
...\> py manage.py ogrinspect [options] <data_source> <model_name> [options]
```

`data_source` is the path to the GDAL-supported data source and
`model_name` is the name to use for the model. Command-line options may
be used to further define how the model is generated.

たとえば、以下のコマンドを実行すると、ほぼ先ほど作成した `WorldBorder` モデルとマッピング辞書を自動的に再現します。

```console
$ python manage.py ogrinspect world/data/TM_WORLD_BORDERS-0.3.shp WorldBorder \
    --srid=4326 --mapping --multi
```

*Windows*

```doscon
...\> py manage.py ogrinspect world\data\TM_WORLD_BORDERS-0.3.shp WorldBorder \
    --srid=4326 --mapping --multi
```

上記のコマンドラインオプションに関していくつかの注意点があります:

- `--srid=4326` オプションは、地理フィールドのSRIDを設定します。
- `--mapping` オプションは、`ogrinspect` に、 [`LayerMapping`](/ja/6.0/ref/contrib/gis/layermapping/#django.contrib.gis.utils.LayerMapping) と一緒に使用するマッピング辞書を生成するよう指示します。
- オプション `--multi` を指定すると、地理フィールドが単なる [`PolygonField`](/ja/6.0/ref/contrib/gis/model-api/#django.contrib.gis.db.models.PolygonField) ではなく [`MultiPolygonField`](/ja/6.0/ref/contrib/gis/model-api/#django.contrib.gis.db.models.MultiPolygonField) になります。

このコマンドは次のような出力をします。GeoDjango アプリケーションの `models.py` に直接コピーできます:

```
# This is an auto-generated Django model module created by ogrinspect.
from django.contrib.gis.db import models

class WorldBorder(models.Model):
    fips = models.CharField(max_length=2)
    iso2 = models.CharField(max_length=2)
    iso3 = models.CharField(max_length=3)
    un = models.IntegerField()
    name = models.CharField(max_length=50)
    area = models.IntegerField()
    pop2005 = models.IntegerField()
    region = models.IntegerField()
    subregion = models.IntegerField()
    lon = models.FloatField()
    lat = models.FloatField()
    geom = models.MultiPolygonField(srid=4326)

# Auto-generated `LayerMapping` dictionary for WorldBorder model
worldborders_mapping = {
    "fips": "FIPS",
    "iso2": "ISO2",
    "iso3": "ISO3",
    "un": "UN",
    "name": "NAME",
    "area": "AREA",
    "pop2005": "POP2005",
    "region": "REGION",
    "subregion": "SUBREGION",
    "lon": "LON",
    "lat": "LAT",
    "geom": "MULTIPOLYGON",
}
```

## 空間クエリ

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

GeoDjango adds spatial lookups to the Django ORM. For example, you
can find the country in the `WorldBorder` table that contains
a particular point. First, fire up the management shell:

```console
$ python manage.py shell
```

*Windows*

```doscon
...\> py manage.py shell
```

ここで、注目するポイント [^3] を定義します:

```pycon
>>> pnt_wkt = "POINT(-95.3385 29.7245)"
```

The `pnt_wkt` string represents the point at -95.3385 degrees longitude,
29.7245 degrees latitude. The geometry is in a format known as
Well Known Text (WKT), a standard issued by the Open Geospatial
Consortium (OGC). [^4]  Import the `WorldBorder` model, and perform
a `contains` lookup using the `pnt_wkt` as the parameter:

```pycon
>>> from world.models import WorldBorder
>>> WorldBorder.objects.filter(mpoly__contains=pnt_wkt)
<QuerySet [<WorldBorder: United States>]>
```

ここでは、米国の国境という1つのモデルのみを持つ `QuerySet` を取得しました (まさに期待通りです)。

Similarly, you may also use a [GEOS geometry object](/ja/6.0/ref/contrib/gis/geos/). Here, you can combine the `intersects` spatial
lookup with the `get` method to retrieve only the `WorldBorder` instance
for San Marino instead of a queryset:

```pycon
>>> from django.contrib.gis.geos import Point
>>> pnt = Point(12.4604, 43.9420)
>>> WorldBorder.objects.get(mpoly__intersects=pnt)
<WorldBorder: San Marino>
```

The `contains` and `intersects` lookups are just a subset of the available
queries -- the [GeoDjango データベース API](/ja/6.0/ref/contrib/gis/db-api/) documentation has more.

### 座標系の自動変換

When doing spatial queries, GeoDjango automatically transforms
geometries if they're in a different coordinate system. In the following
example, coordinates will be expressed in [EPSG SRID 32140](https://spatialreference.org/ref/epsg/32140/),
a coordinate system specific to south Texas **only** and in units of
**meters**, not degrees:

```pycon
>>> from django.contrib.gis.geos import GEOSGeometry, Point
>>> pnt = Point(954158.1, 4215137.1, srid=32140)
```

`pnt` は、SRIDを含むWKTの拡張形式であるEWKTで構築することもできることに注意してください。

```pycon
>>> pnt = GEOSGeometry("SRID=32140;POINT(954158.1 4215137.1)")
```

GeoDjango の ORM は、ジオメトリの値を自動的に変換 SQL でラップし、開発者がより高い抽象度で作業できるようにします:

```pycon
>>> qs = WorldBorder.objects.filter(mpoly__intersects=pnt)
>>> print(qs.query)  # Generating the SQL
SELECT "world_worldborder"."id", "world_worldborder"."name", "world_worldborder"."area",
"world_worldborder"."pop2005", "world_worldborder"."fips", "world_worldborder"."iso2",
"world_worldborder"."iso3", "world_worldborder"."un", "world_worldborder"."region",
"world_worldborder"."subregion", "world_worldborder"."lon", "world_worldborder"."lat",
"world_worldborder"."mpoly" FROM "world_worldborder"
WHERE ST_Intersects("world_worldborder"."mpoly", ST_Transform(%s, 4326))
>>> qs  # printing evaluates the queryset
<QuerySet [<WorldBorder: United States>]>
```

> **素のクエリ**
>
> [素のクエリ](/ja/6.0/topics/db/sql/) を使用する際は、ジオメトリフィールドをラップして、そのフィールド値が GEOS に認識されるようにする必要があります。
>
> ```pycon
> >>> from django.db import connection
> >>> # or if you're querying a non-default database:
> >>> from django.db import connections
> >>> connection = connections["your_gis_db_alias"]
> >>> City.objects.raw(
> ...     "SELECT id, name, %s as point from myapp_city" % (connection.ops.select % "point")
> ... )
> ```
>
> 素のクエリを使うのは、自分が何をしているのかよく分かっている場合に限定されるべきです。

### ジオメトリの遅延評価

GeoDjango loads geometries in a standardized textual representation. When the
geometry field is first accessed, GeoDjango creates a
[`GEOSGeometry`](/ja/6.0/ref/contrib/gis/geos/#django.contrib.gis.geos.GEOSGeometry) object, exposing powerful
functionality, such as serialization properties for popular geospatial
formats:

```pycon
>>> sm = WorldBorder.objects.get(name="San Marino")
>>> sm.mpoly
<MultiPolygon object at 0x24c6798>
>>> sm.mpoly.wkt  # WKT
MULTIPOLYGON (((12.4157980000000006 43.9579540000000009, 12.4505540000000003 43.9797209999999978, ...
>>> sm.mpoly.wkb  # WKB (as Python binary buffer)
<read-only buffer for 0x1fe2c70, size -1, offset 0 at 0x2564c40>
>>> sm.mpoly.geojson  # GeoJSON
'{ "type": "MultiPolygon", "coordinates": [ [ [ [ 12.415798, 43.957954 ], [ 12.450554, 43.979721 ], ...
```

これには、GEOSライブラリが提供するすべての高度な幾何演算へのアクセスが含まれます:

```pycon
>>> pnt = Point(12.4604, 43.9420)
>>> sm.mpoly.contains(pnt)
True
>>> pnt.contains(sm.mpoly)
False
```

### 地理情報のアノテーション

GeoDjango also offers a set of geographic annotations to compute distances and
several other operations (intersection, difference, etc.). See the
[地理情報データベース関数](/ja/6.0/ref/contrib/gis/functions/) documentation.

## データを地図上に配置する

### 地理情報の Admin

[Django の admin アプリケーション](/ja/6.0/ref/contrib/admin/) はジオメトリフィールドの編集をサポートしています。

#### 基本

Django のadmin アプリケーションでは、ユーザが JavaScript のスリッピーマップ ([OpenLayers](https://openlayers.org/) を利用) 上でジオメトリを作成したり変更したりできます。

さあ、始めましょう。次のコードを含む `world` アプリケーション内に `admin.py` という名前のファイルを作成します:

```
from django.contrib.gis import admin
from .models import WorldBorder

admin.site.register(WorldBorder, admin.ModelAdmin)
```

次に、 `geodjango` アプリケーションフォルダにある `urls.py` を以下のように編集してください:

```
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path("admin/", admin.site.urls),
]
```

admin ユーザーを作成します:

```console
$ python manage.py createsuperuser
```

*Windows*

```doscon
...\> py manage.py createsuperuser
```

次に、Django 開発サーバを起動します:

```console
$ python manage.py runserver
```

*Windows*

```doscon
...\> py manage.py runserver
```

最後に `http://localhost:8000/admin/` にアクセスし、先ほど作成したユーザーでログインします。 `WorldBorder` のエントリーをブラウズし、ポリゴンをクリックして頂点を好きな位置までドラッグすることで、境界線を編集できます。

#### `GISModelAdmin`

[`GISModelAdmin`](/ja/6.0/ref/contrib/gis/admin/#django.contrib.gis.admin.GISModelAdmin) を使用すると、GeoDjango は admin アプリケーションで [OpenStreetMap](https://www.openstreetmap.org/) レイヤーを使用します。これにより、 [`ModelAdmin`](/ja/6.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin) が使用する [Vector Map Level 0](http://web.archive.org/web/20201024202709/https://earth-info.nga.mil/publications/vmap0.html) WMSデータセット ([OSGeo](https://www.osgeo.org/) でホストされている) よりも、より多くのコンテキスト (通りや通路の詳細を含む) が提供されます。

PROJの座標変換ファイルがインストールされている必要があります (詳しくは [PROJ installation instructions](/ja/6.0/ref/contrib/gis/install/geolibs/#proj4) を参照してください) 。

この要件を満たしている場合は、 `admin.py` ファイルで `GISModelAdmin` オプションクラスを使用してください:

```
admin.site.register(WorldBorder, admin.GISModelAdmin)
```

**脚注**

[^1]: このデータセットの提供およびメンテナンスをしてくれた [mastermaps.net](https://mastermaps.net/) の Bjørn Sandvik 氏に特別な感謝を申し上げます。

[^2]: GeoDjango の基本アプリは、Dane Springmeyer、Josh Livni、およびChristopher Schmidt によって記述されました。

[^3]: このポイントは [ヒューストン大学法科大学院](https://www.law.uh.edu/) です。

[^4]: Open Geospatial Consortium, Inc, [OpenGIS Simple Feature Specification For SQL](https://www.ogc.org/standards/sfs).
