目次
こんにちは。sinyです。
本記事ではDjangoで地図アプリを作成できるGeoDjangoの入門チュートリアルということで記事にしてみました。
GeoDjangoとは
GeoDjangoはDjangoに標準で組み込まれている地理空間情報(GIS)を扱うためのモジュールです。
Geographic Information System の頭文字をとり、GISと言います。
GeoDjangoを使うと以下のようなマップWEBアプリを開発できます。
なお、GeoDjangoを利用するにあたってGISの基本的な概念や知識について把握しておくと理解が進むので、以下のサイト等を参考に基本知識を事前学習しておくことをお勧めします。
GeoDjango環境構築手順
この記事では以下の前提で環境構築を行います。
項目 | バージョン |
OS | Windows10 |
データベース | PostGres10.12-1 |
Python | 3.6.5 |
Django | 3.0.3 |
psycopg2 | 2.8.4 |
django-leaflet | 0.26.0 |
Pythonのインストール
Pythonのインストール手順はここでは割愛します。
以下のサイト等を参考にインストールしてください。
PostgreSQLのインストール
以下のサイトから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ユーザのパスワードを入力します。
GeoDjango環境の作成
ここからはDjangoとGeoDjangoの環境を作成しています。
仮想環境作成
ここではmyenvという仮想環境を作成した後アクティベートを行っておきます。
python -m venv myenv cd myenv scripts\activate
モジュールのインストール
pipコマンドを使って以下のモジュールをインストールします。
pip install django pip install psycopg2 pip insatll six
from django.utils import six
ImportError: cannot import name 'six'
OSGeo4Wのインストール
GeoDjangoをWindows環境で利用するにはOSGeo4Wをインストールする必要があります。
以下のサイトから64bit版のOSGeo4Wインストーラをダウンロードします。
ダウンロードしたインストーラをクリックしてOSGeo4Wをインストールしていきます。
「エクスプレスWeb-GISインストーラ」を選択してインストールします。
パッケージは「GDAL」だけにチェック入れます。
後はデフォルトのままインストールすればOKです。
データベース作成
GeoDjangoで利用するデータベースを作成します。
今回は以下のコマンドでgeodjangodbという名称のデータベースを作成します。
createdb -U postgres -E UTF-8 geodjangodb
以下のコマンドでpostgresSQLに接続して、\lコマンドでDB一覧を確認します。
psql -U postgres -d postgres postgres=# \l
PostGISのエクステンションを作成
続いてGISを扱うためのPostGISエクステンションを作成します。
psql -U postgres -d geodjangodb -c "CREATE EXTENSION postgis;" ユーザー postgres のパスワード: CREATE EXTENSION
以下のコマンドでエクステンションが生成されていることを確認します。
psql -U postgres -d geodjangodb select * from pg_available_extensions;
DB管理ユーザを作成
続いて先ほど作成したデータベースの管理ユーザを作成します。
以下のコマンドではgeo_adminという管理ユーザを作成して、geodjangodbデータベースに対してフル権限を付与しています。
CREATE USER geo_admin WITH PASSWORD 'geoadmin'; CREATE ROLE GRANT ALL PRIVILEGES ON DATABASE geodjangodb TO geo_admin; GRANT
Djangoプロジェクトを作成する
通常のDjangoプロジェクトを作成します。(プロジェクト名:tutorial)
django-admin startproject tutorial
アプリケーションを作成する
mapという名称でdjangoアプリケーションを作成します。
cd tutorial python manage.py startapp map
settings.pyのカスタマイズ
まずは利用するデータベースをデフォルトのSqliteからPostGISに変更します。
※ユーザ名とパスワードは先ほど作成したDB管理用ユーザ(geo_admin)を指定
DATABASES = { 'default': { 'ENGINE': 'django.contrib.gis.db.backends.postgis', 'NAME': 'geodjangodb', 'USER': 'geo_admin', 'PASSWORD': 'geoadmin', 'HOST': 'localhost', 'PORT':'', } }
次にタイムゾーンなどを日本語に変更しておきます。
LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC'
続いてINSTALLED_APPSにmapアプリケーションとGISを追加します。
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 manage.py makemigrations
すると、以下のエラーが発生するのでこのエラーを回避するための設定を行います。
まず、settings.pyに以下の環境設定を追加します。
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を追加します。
変更前
elif os.name == 'nt': # Windows NT shared libraries lib_names = ['gdal204', 'gdal203', 'gdal202', 'gdal201', 'gdal20']
変更後
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 manage.py makemigrations No changes detected
一旦マイグレートを実行しておきます。
python manage.py migrate
※補足
もし以下のようなエラーが出る場合は\myenv\Scripts\sqlite.dllをリネームします。
※これはC:\OSGeo4W64\bin\sqlite.dllと競合することが原因で発生する。
Djangoの管理者ユーザも作成しておきます。
python manage.py createsuperuser
インポートデータの準備と登録
この記事では、G空間情報センターで公開されている指定緊急避難場所データ_13東京都(GeoJson)のデータを使って、避難場所のデータをGeodjangoにインポートします。
避難場所のデータは以下のサイトからGeojson形式のデータを取得できます。
- URL=指定緊急避難場所データ_13東京都(GeoJson)
取得したgeojsonデータをhinanbasho.geojsonとしてdjangoプロジェクト直下に配置します。
まずは、取得したgeojsonのデータをDjangoのモデルに落とし込むためにdjangoのogrinspectコマンドを使ってデータ構造をチェックします。
python manage.py ogrinspect --srid=4326 hinanbasho.geojson Evacuation
実行結果は以下のようになります。
# 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 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 manage.py makemigrations python manage.py migrate
続いて、サンプルデータをデータベースへ登録するスクリプトを作成します。
mapアプリケーション直下にload_data.pyというファイルを作成して以下のコードを記載します。
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フォルダ直下に配置した後に以下のコマンドを実行してデータベースへ登録します。
python manage.py shell from map import load_data load_data.run() Saved: 東京都立三宅高等学校体育館 Saved: 小笠原小中学校 Saved: 小笠原高等学校 Saved: 奥村交流センター Saved: 扇浦交流センター Saved: 地域福祉センター Saved: 母島支所大広間 Saved: 母島診療所駐車場 Saved: 母島小中学校 Saved: 評議平運動場 >>>
管理画面の設定
admin.pyに以下の設定を行い登録したデータを参照できるようにします。
from django.contrib.gis import admin from map.models import Evacuation admin.site.register(Evacuation, admin.GeoModelAdmin)
上記設定をするとadminサイト上で以下のような地図データ入りのデータが登録されていることが確認できます。
この状態だと地図のデザインがあまり行けていないので、もう少し見た目の良いデザインに変更してみます。
django-leafletというモジュールを使うと簡単にデザインを変更することができます。
まずpipでdjango-leafletをインストールします。
pip install django-leaflet
settings.pyにleafletを登録します。
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を以下のように変更します。
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サイト上で表示するところまで解説しました。
このチュートリアルノートでは下記動画のような地図アプリをDjangoで開発できる内容になっています。