はじめに
MacOS上に、GIS(地理空間情報)を扱えるように、GeoDjango+PostGIS環境を構築した手順のメモです。MacOSのターミナル操作ができ、Django/PostGISはよくわからなくても構築できるレベルで記載。ただし途中でやり直したので、手順のズレや漏れがあるかもしれません。
(追記)バージョンを修正
-
環境
- MacBook Pro (2020)
- macOS BigSur 11.4
- Homebrew 3.1.11
-
インストールバージョン
- Python 3.9.6
- Django 3.2.6
- PostgreSQL 13.4
- PostGIS 3.1.2
環境構築
Python
- ターミナルでまず xcode を導入し、python3.9を brew で入れる
% sudo rm -r /Library/Developer/CommandLineTools # 念のため既存のコマンドラインツールを削除
% xcode-select --install # コマンドラインツールをインストール
% brew install python@3.9
(注) MacOSのアップデートにより、xcode-selectの再導入が必要になる場合がある
(注) この手順では、公式Python3のpkg版はアンインストールした方が無難
参考:https://code-graffiti.com/how-to-uninstall-official-python3-on-mac/
※ (省略可)pyenvでpythonのバージョンを切り替える場合
% brew update && brew upgrade pyenv # 念のためpyenvを更新
% pyenv install --list # インストールできるバージョンの確認
% pyenv install 3.9.6 # バージョン指定して python をインストール
% pyenv global 3.9.6 # 全体で 3.9.6 を利用するように設定
% python -V # pythonのバージョン確認
Python 3.9.6
% vi ~/.zprofile
export PYENV_ROOT="$HOME/.pyenv" # PATHを追加
export PATH="$PYENV_ROOT/bin:$PATH" # PATHを追加
eval "$(pyenv init -)"
Venv仮想環境
venvを使い、対象ごとにpython環境を管理
% python -m venv test # 任意の環境名(ここではtest)を作成
% source test/bin/activate # test環境に切り替え
(test) %
参考: deactivate でもとの環境に戻る
Django
test環境で、pip自身をアップグレードしてからDjangoを導入
(test) % pip install --upgrade pip
(test) % pip install django psycopg2 django-geojson
(test) % python -m django --version # djangoのバージョン確認
3.2.6
PostgreSQL+PostGIS
PostgraSQLデータベースと、そのGIS拡張のPostGISをインストール。
% brew install postgres
% brew install postgis
念の為 /usr/local/var/postgres を初期化し、postgresユーザを作成
% initdb /usr/local/var/postgres -E utf8
% createuser -s postgres
PostgreSQLを起動
brew services start postgresql
GDAL
GISライブラリであるGDALをインストール
brew install gdal
設定
Django初期プロジェクト
空プロジェクトを作成し、そのまま起動
% django-admin startproject testmap
% cd testmap
% ./manage.py runserver
http://localhost:8000 にアクセスし、 "The install worked successfully! Congratulations!" 「インストールは成功しました!おめでとうございます!」もしくは Django administration のログイン画面が表示されれば、Djangoプロジェクトはできている。
確認できればCtrl-Cで終了。再起動時はvenvでpython環境を変えるを忘れずに。
データベースの作成
通常のPostgreデータベースと、PostGIS拡張データベースを作成
% createdb -U postgres testdb # 通常のデータベースの場合
% createdb -U postgres postgisdb # DB作成後PostGIS拡張を適用する手順
% psql -U postgres postgisdb
psql (13.3)
Type "help" for help.
postgisdb=# CREATE EXTENSION postgis;
CREATE EXTENSION
postgisdb=# SELECT PostGIS_Version();
postgis_version
---------------------------------------
3.1 USE_GEOS=1 USE_PROJ=1 USE_STATS=1
(1 row)
ついでに対象DBのみにアクセス権限を持つユーザも作っておく
postgisdb=# CREATE USER dbuser WITH PASSWORD 'passwords';
CREATE ROLE
postgisdb=# GRANT ALL PRIVILEGES ON DATABASE postgisdb TO dbuser;
GRANT
postgisdb=# ¥q
Djangoの設定
testmap/setting.py
作成したプロジェクト配下のsetting.pyの以下の部分を編集
- GIS指定と、作成したプロジェクトのアプリを追加
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.gis', # 追加:GIS機能
’testmap', # 追加:作成したプロジェクト
]
- データベースの設定
DATABASES = {
'default': {
'ENGINE': 'django.contrib.gis.db.backends.postgis',
'HOST': 'localhost', # DBホスト
'NAME': 'postgisdb', # データベース名
'USER': 'dbuser', # DBユーザ名
'PASSWORD': 'passwords', # DBパスワード
}
}
- 文字コードと時刻設定(必要に応じて)
LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'
データベース設定
- Djangoが利用するテーブルを作成
% ./manage.py makemigrations
No changes detected
% ./manage.py migrate
Operations to perform:
[中略]
Applying sessions.0001_initial... OK
Django管理ユーザを作成
% ./manage.py createsuperuser
ユーザー名 (leave blank to use 'geojson'): testmap
メールアドレス: testmap@example.com
Password:
Password (again):
geojsonデータを表示
表示データ
- 準備
サンプルとして、国土数値情報ダウンロードサービス http://nlftp.mlit.go.jp/ksj/index.html から行政境界(ポリゴン)をダウンロード。全国だとサイズが大きいので適当な都道府県(今回は奈良県)を選び、ダウンロードしたN03-20200101_29_GML.zipを展開。
含まれている N03_20_29_200101.geojson を djangoプロジェクト直下に配置
- 形式の確認
どのような要素があるか確認。
% ./manage.py ogrinspect --srid=4326 N03-20_29_200101.geojson Border
# This is an auto-generated Django model module created by ogrinspect.
from django.contrib.gis.db import models
class Border(models.Model):
n03_001 = models.CharField(max_length=0)
n03_002 = models.CharField(max_length=0)
n03_003 = models.CharField(max_length=0)
n03_004 = models.CharField(max_length=0)
n03_007 = models.CharField(max_length=0)
_color = models.CharField(max_length=0)
_opacity = models.IntegerField()
_weight = models.IntegerField()
_fillcolor = models.CharField(max_length=0)
_fillopacity = models.FloatField()
geom = models.PolygonField(srid=4326)
※ データの座標系がJGD2011なので、世界座標系のsrid=4326を指定。一般にGPS測位はこれを利用。
データモデル
testmap/models.py で行政境界のモデルを定義します。models.pyがなければ作成。
Django 3.2.4 ではワーニングがでるのでidを追加し、__unicode__を str に修正。
from django.contrib.auth import get_user_model
from django.contrib.gis.db import models
class Border(models.Model):
id = models.AutoField(primary_key=True)
n03_001 = models.CharField(verbose_name='都道府県名', max_length=10)
n03_002 = models.CharField(verbose_name='支庁名', max_length=20, blank=True)
n03_003 = models.CharField(verbose_name='群・政令市名', max_length=20, blank=True)
n03_004 = models.CharField(verbose_name='市区町村名', max_length=20, blank=True)
n03_007 = models.CharField(verbose_name='行政区域コード', max_length=5)
geom = models.PolygonField(srid=4612)
objects = models.Manager()
def __str__(self):
return "%s_%s_%s" % (self.n03_001,self.n03_003,self.n03_004)
class Meta:
verbose_name = "行政区域"
verbose_name_plural = "行政区域一覧"
マイグレーション実行しモデルで定義したテーブルを作成
% ./manage.py makemigrations testmap # アプリを指定してマイグレーション作成
% ./manage.py migrate # マイグレーション実行
データインポート
- geojsonファイルをデータベースに登録するスクリプト load_nara.py を作成
どこに作っても良いが、Djangoプロジェクト直下に置く。
import os
from django.contrib.gis.utils import LayerMapping
from testmap.models import Border
# ModelとGeojsonのマッピング
mapping = {
'n03_001' : 'N03_001',
'n03_002' : 'N03_002',
'n03_003' : 'N03_003',
'n03_004' : 'N03_004',
'n03_007' : 'N03_007',
'geom' : 'POLYGON',
}
# geojsonファイル
geojson_file = os.path.abspath(os.path.join(os.path.dirname(__file__), 'N03-20_29_200101.geojson'))
# 実行
def run(verbose=True):
lm = LayerMapping(Border, geojson_file, mapping, transform=False, encoding='UTF-8')
lm.save(strict=True, verbose=verbose)
- Djangoシェルで、作成したスクリプトを実行
% ./manage.py shell
>>> from . import load_nara
>>> load_nara.run()
Saved: 奈良県__奈良市
[snip]
>>> ^D
管理者画面で確認
testmap/admin.py に以下のように記述(なければ作成)。OSMGeoAdminで背景地図はOSMを指定。
from django.contrib import admin
from django.contrib.gis import admin as geoadmin
from . import models
# Border
admin.site.register(models.Border, geoadmin.OSMGeoAdmin)
テストサーバを起動
% ./manage.py runserver
http://localhost:8000/admin にアクセスし、createsuperuser で作成したユーザID/パスワードでログインします。
正しく設定ができていれば、管理サイトページに表示された行政区域一覧テーブルを選択すると、各市町村のレコードがあり、例えば生駒市を選択すると、下のように地図上に境界が表示される。
以上で環境構築とデータ投入の確認まで完了。
アプリケーション作成
最低限の環境が構築できたので、この先は、geojsonデータを利用したアプリケーションやWebAPIをDjangoフレームワークを使い作って行きます。
参考
- GeoDjangoではじめる地理空間情報 https://homata.gitbook.io/geodjango/hajimeni/readme
- 測地系と座標系 https://homata.gitbook.io/geodjango/hajimeteno/coordinate