GeoDjango 入門|地図アプリを Django で作る完全チュートリアル(PostGIS + 空間検索)

スポンサードリンク



Django · GIS · GeoDjango 入門

図データを扱うアプリ(店舗検索・配送ルート・不動産マップ等)を Django で開発するなら、Django 公式の GIS フレームワーク GeoDjango が定番です。緯度経度を持つモデル定義、距離計算、空間インデックス、地図表示までを Django の標準機能の延長で実装できます。本記事では PostGIS バックエンドを使った GeoDjango の基礎セットアップから、サンプルアプリでの空間検索実装までを完全解説します。

本記事ではDjangoで地図アプリを作成できるGeoDjangoの入門チュートリアルということで記事にしてみました。

user@sinyblog:~/article 01_geodjango.mdGeoDjangoとは

GeoDjangoはDjangoに標準で組み込まれている地理空間情報(GIS)を扱うためのモジュールです。

Geographic Information System の頭文字をとり、GISと言います。

GeoDjangoを使うと以下のようなマップWEBアプリを開発できます。

なお、GeoDjangoを利用するにあたってGISの基本的な概念や知識について把握しておくと理解が進むので、以下のサイト等を参考に基本知識を事前学習しておくことをお勧めします。

user@sinyblog:~/article 02_geodjango.mdGeoDjango環境構築手順

この記事では以下の前提で環境構築を行います。

項目 バージョン
OS Windows10
データベース PostGres10.12-1
Python 3.6.5
Django 3.0.3
psycopg2 2.8.4
django-leaflet 0.26.0

 

user@sinyblog:~/article 03_python.mdPythonのインストール

Pythonのインストール手順はここでは割愛します。

以下のサイト等を参考にインストールしてください。

 

user@sinyblog:~/article 04_postgresql.mdPostgreSQLのインストール

以下のサイトからWindows x86-64のPostgresバージョン10.12のインストーラをダウンロードしてインストールします。

基本的にデフォルト設定のままでOKですが、Localeの設定ではJapanを選びます。

Postgresのインストールが終わると以下の画面が表示されるのでそのまま「Finish」ボタンを押してStack Builderを起動します。

Stack Builderを使ってPostGISをインストールしていきます。

スタックビルダーの画面が表示されるので、インストールしたPostgreSQL10を選択して「次へ」ボタンを押します。

今回はPostGIS 2.4(64bit)を選択します。

あとは基本的にデフォルトのままで進めていけばOKです。

以下のようなメッセージが表示されますがすべて「はい」を選びます。

インストールが終わると以下の画面が表示されます。

PostgreSQL/PostGIS環境変数、パスの設定

システム環境変数のPATHに「C:\Program Files\PostgreSQL\10\bin」を追加しておきます。

最後にDOSを起動して「psql -U postgres -l」でDBにログオンできればOKです。

※パスワードはインストール時に指定してpostgresユーザのパスワードを入力します。

user@sinyblog:~/article 05_geodjango.mdGeoDjango環境の作成

ここからはDjangoとGeoDjangoの環境を作成しています。

仮想環境作成

ここではmyenvという仮想環境を作成した後アクティベートを行っておきます。

python


python -m venv myenv

cd myenv

scripts\activate

 

モジュールのインストール

pipコマンドを使って以下のモジュールをインストールします。

python


pip install django

pip install psycopg2

pip insatll six



 

 Djangoバージョン3.0を入れると以下のエラーが発生したのでpipコマンドで明示的にsixモジュールをインストールすることで解消しました。

from django.utils import six

ImportError: cannot import name 'six'

 

OSGeo4Wのインストール

GeoDjangoをWindows環境で利用するにはOSGeo4Wをインストールする必要があります。

以下のサイトから64bit版のOSGeo4Wインストーラをダウンロードします。

ダウンロードしたインストーラをクリックしてOSGeo4Wをインストールしていきます。

「エクスプレスWeb-GISインストーラ」を選択してインストールします。

パッケージは「GDAL」だけにチェック入れます。

 

後はデフォルトのままインストールすればOKです。

データベース作成

GeoDjangoで利用するデータベースを作成します。

今回は以下のコマンドでgeodjangodbという名称のデータベースを作成します。

default


createdb -U postgres -E UTF-8 geodjangodb

以下のコマンドでpostgresSQLに接続して、\lコマンドでDB一覧を確認します。

default


psql -U postgres -d postgres

postgres=# \l

PostGISのエクステンションを作成

続いてGISを扱うためのPostGISエクステンションを作成します。

default


psql -U postgres -d geodjangodb -c "CREATE EXTENSION postgis;"

ユーザー postgres のパスワード:

CREATE EXTENSION

以下のコマンドでエクステンションが生成されていることを確認します。

default


psql -U postgres -d geodjangodb

select * from pg_available_extensions;

DB管理ユーザを作成

続いて先ほど作成したデータベースの管理ユーザを作成します。

以下のコマンドではgeo_adminという管理ユーザを作成して、geodjangodbデータベースに対してフル権限を付与しています。

default


CREATE USER geo_admin WITH PASSWORD 'geoadmin';

CREATE ROLE

GRANT ALL PRIVILEGES ON DATABASE geodjangodb TO geo_admin;

GRANT

 

Djangoプロジェクトを作成する

通常のDjangoプロジェクトを作成します。(プロジェクト名:tutorial)

python


django-admin startproject tutorial

 

アプリケーションを作成する

mapという名称でdjangoアプリケーションを作成します。

python


cd tutorial

python manage.py startapp map

 

settings.pyのカスタマイズ

まずは利用するデータベースをデフォルトのSqliteからPostGISに変更します。

※ユーザ名とパスワードは先ほど作成したDB管理用ユーザ(geo_admin)を指定

python


DATABASES = {		

    'default': {		

        'ENGINE': 'django.contrib.gis.db.backends.postgis',		

        'NAME': 'geodjangodb',		

        'USER': 'geo_admin',		

        'PASSWORD': 'geoadmin',		

        'HOST': 'localhost',		

        'PORT':'',		

    }		

}		

次にタイムゾーンなどを日本語に変更しておきます。

python


LANGUAGE_CODE = 'en-us'



TIME_ZONE = 'UTC'

続いてINSTALLED_APPSにmapアプリケーションとGISを追加します。

python


INSTALLED_APPS = [

    'django.contrib.admin',

    'django.contrib.auth',

    'django.contrib.contenttypes',

    'django.contrib.sessions',

    'django.contrib.messages',

    'django.contrib.staticfiles',

   'django.contrib.gis',   #追加

    'map.apps.MapConfig',   #追加

]

ここまで設定したら一旦Djangoマイグレーションを実行します。

python


python manage.py makemigrations

すると、以下のエラーが発生するのでこのエラーを回避するための設定を行います。

 django.core.exceptions.ImproperlyConfigured: Could not find the GDAL library (tried "gdal300", "gdal204", "gdal203", "gdal202", "gdal201", "gdal20"). Is GDAL installed? If it is, try setting GDAL_LIBRARY_PATH in your settings.

 

まず、settings.pyに以下の環境設定を追加します。

python


import os

if os.name == 'nt':

    import platform

    POSTGRES = r"C:\Program Files\PostgreSQL\10"

    OSGEO4W = r"C:\OSGeo4W"

    if '64' in platform.architecture()[0]:

        OSGEO4W += "64"

    assert os.path.isdir(OSGEO4W), "Directory does not exist: " + OSGEO4W



    os.environ['OSGEO4W_ROOT'] = OSGEO4W

    os.environ['POSTGRES_ROOT'] = POSTGRES

    os.environ['GDAL_LIBRARY_PATH'] = OSGEO4W + r"\bin"

    os.environ['GEOS_LIBRARY_PATH'] = OSGEO4W + r"\bin"

    os.environ['GDAL_DATA'] = OSGEO4W + r"\share\gdal"

    os.environ['PROJ_LIB'] = OSGEO4W + r"\share\proj"

    os.environ['PATH'] = OSGEO4W + r"\bin;" + POSTGRES + r"\bin;" + os.environ['PATH']

 

さらに仮想環境は以下にあるDjangoのファイル(myenv\Lib\site-packages\django\contrib\gis\gdal\libgdal.py)にgdal300を追加します。

変更前

python


elif os.name == 'nt':

# Windows NT shared libraries

lib_names = ['gdal204', 'gdal203', 'gdal202', 'gdal201', 'gdal20']

 

変更後

python


elif os.name == 'nt':

# Windows NT shared libraries

lib_names = ['gdal300', 'gdal204', 'gdal203', 'gdal202', 'gdal201', 'gdal20']

gdal300はC:\OSGeo4W64\bin\gdal300.dllを指します。

再度makemigrationsを実行してエラーが出なくなればOKです。

python


python manage.py makemigrations

No changes detected

 

一旦マイグレートを実行しておきます。

python


python manage.py migrate

 

※補足

もし以下のようなエラーが出る場合は\myenv\Scripts\sqlite.dllをリネームします。

※これはC:\OSGeo4W64\bin\sqlite.dllと競合することが原因で発生する。

Djangoの管理者ユーザも作成しておきます。

python


python manage.py createsuperuser

 

user@sinyblog:~/article 06_section_6.mdインポートデータの準備と登録

この記事では、G空間情報センターで公開されている指定緊急避難場所データ_13東京都(GeoJson)のデータを使って、避難場所のデータをGeodjangoにインポートします。

避難場所のデータは以下のサイトからGeojson形式のデータを取得できます。

Pz-LinkCard
- URLの記述に誤りがあります。
- URL=指定緊急避難場所データ_13東京都(GeoJson)

取得したgeojsonデータをhinanbasho.geojsonとしてdjangoプロジェクト直下に配置します。

まずは、取得したgeojsonのデータをDjangoのモデルに落とし込むためにdjangoのogrinspectコマンドを使ってデータ構造をチェックします。

python


python manage.py ogrinspect --srid=4326 hinanbasho.geojson Evacuation

実行結果は以下のようになります。

default


# This is an auto-generated Django model module created by ogrinspect.

from django.contrib.gis.db import models





class Evacuation(models.Model):

    指定緊急避難場所 = models.CharField(max_length=0)

    所在地 = models.CharField(max_length=0)

    洪水 = models.CharField(max_length=0)

    がけ崩れ、土石流及び地滑り = models.CharField(max_length=0)

    高潮 = models.CharField(max_length=0)

    地震 = models.CharField(max_length=0)

    津波 = models.CharField(max_length=0)

    大規模な火事 = models.CharField(max_length=0)

    内水氾濫 = models.CharField(max_length=0)

    火山現象 = models.CharField(max_length=0)

    geom = models.PointField(srid=4326)

カラム名が日本語になっているのでアルファベットに変更し、max_lengthを適宜修正したらmodes.pyにモデルの定義を記載します。

今回は以下のようにモデルを定義します。

注意点は、通常のdjango.dbのmodelsではなくgis用のmodelsをインポートしている点です。

#from django.db import models

     ↓

from django.contrib.gis.db import models
python


#from django.db import models

from django.contrib.gis.db import models



class Evacuation(models.Model):

    evacuation_site = models.CharField(max_length=255)

    location = models.CharField(max_length=255)

    flood = models.CharField(max_length=255)

    landslides = models.CharField(max_length=255)

    storm_surge = models.CharField(max_length=255)

    earthquake = models.CharField(max_length=255)

    tsunami = models.CharField(max_length=255)

    massive_fire = models.CharField(max_length=255)

    inland_flooding = models.CharField(max_length=255)

    volcanic_phenomena = models.CharField(max_length=255)

    geom = models.PointField(srid=4326)



    def __str__(self):

        return self.evacuation_site

テーブルをDBに反映させるためマイグレーションを行います。

python


python manage.py makemigrations

python manage.py migrate

続いて、サンプルデータをデータベースへ登録するスクリプトを作成します。

mapアプリケーション直下にload_data.pyというファイルを作成して以下のコードを記載します。

python


import os

from django.contrib.gis.utils import LayerMapping

from map.models import Evacuation

# Modelとファイルのカラムのマッピング

mapping = {



    'evacuation_site': '指定緊急避難場所',

    'location': '所在地',

    'flood': '洪水',

    'landslides': 'がけ崩れ、土石流及び地滑り',

    'storm_surge' : '高潮',

    'earthquake': '地震',

    'tsunami': '津波',

    'massive_fire': '大規模な火事',

    'inland_flooding': '内水氾濫',

    'volcanic_phenomena': '火山現象',

    'geom' : 'POINT',

}



# ファイルパス

geojson_file = os.path.abspath(

   os.path.join(os.path.dirname(__file__), 'data','export.geojson'))



# 実行

def run(verbose=True):

    lm = LayerMapping(Evacuation, geojson_file,    

         mapping,transform=False, encoding='UTF-8')

    lm.save(strict=True, verbose=verbose)

 

LayerMappingクラスを使ってDjangoのmodels.pyで定義したカラム名とgeojsonファイル内に定義されているカラム名のマッピング情報を定義しています。

mappingの左側がDjangoのカラム名、右側がgeojsonファイル内の定義名です。

続いてhinanbasho.geojsonをmap\dataフォルダ直下に配置した後に以下のコマンドを実行してデータベースへ登録します。

default


python manage.py shell

from map import load_data

load_data.run()



Saved: 東京都立三宅高等学校体育館	

Saved: 小笠原小中学校	

Saved: 小笠原高等学校	

Saved: 奥村交流センター	

Saved: 扇浦交流センター	

Saved: 地域福祉センター	

Saved: 母島支所大広間	

Saved: 母島診療所駐車場	

Saved: 母島小中学校	

Saved: 評議平運動場	

>>>                      	

 

管理画面の設定

admin.pyに以下の設定を行い登録したデータを参照できるようにします。

default


from django.contrib.gis import admin

from map.models import Evacuation



admin.site.register(Evacuation, admin.GeoModelAdmin)

 

上記設定をするとadminサイト上で以下のような地図データ入りのデータが登録されていることが確認できます。

この状態だと地図のデザインがあまり行けていないので、もう少し見た目の良いデザインに変更してみます。

django-leafletというモジュールを使うと簡単にデザインを変更することができます。

まずpipでdjango-leafletをインストールします。

default


 pip install django-leaflet

settings.pyにleafletを登録します。

python


INSTALLED_APPS = [

    'django.contrib.admin',

    'django.contrib.auth',

    'django.contrib.contenttypes',

    'django.contrib.sessions',

    'django.contrib.messages',

    'django.contrib.staticfiles',

    'django.contrib.gis',   #追加

    'map.apps.MapConfig',   #追加

    'leaflet', #追加

]

 

最後にadmin.pyを以下のように変更します。

python


from django.contrib.gis import admin

from map.models import Evacuation

from leaflet.admin import LeafletGeoAdmin



admin.site.register(Evacuation, LeafletGeoAdmin)

先ほどのadminサイト上のデータ画面を更新し以下のように地図のデザインが変わればOKです。

 

今回は登録したGISデータをdjangoのadminサイト上で表示するところまで解説しました。

 

おすすめの記事