GeoDjango入門チュートリアル

スポンサードリンク



こんにちは。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

 

 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という名称のデータベースを作成します。

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

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

 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に以下の環境設定を追加します。

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形式のデータを取得できます。

Pz-LinkCard
- URLの記述に誤りがあります。
- 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
#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サイト上で表示するところまで解説しました。

 

おすすめの記事