たぶん動く...

多分GIS系の人。あくまで個人的見解であり、所属団体を代表するものではありません。

GeoDjangoをUbuntu環境で構築する(2)

だいぶ前の記事でgeodjangoサーバーを起動するところまで実施しました。
今回は、実際にデータを投入するところを実施してみたいと思います。

前回の記事はこちら tty6335.hatenablog.com

データを準備

今回は、USGSが公開している、過去1日分の全地震データ のGeoJsonファイルを使用します。

djangoに追加したGIS機能のogrinspectを使用して、geojsonの要素を調べます。 まずcatコマンドで中身を簡単に把握します。

$ cat all_day.geojson | jq --tab . | more
{
        "type": "FeatureCollection",
        "metadata": {
                "generated": 1636270889000,
                "url": "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson",
                "title": "USGS All Earthquakes, Past Day",
                "status": 200,
                "api": "1.10.3",
                "count": 201
        },
        "features": [
                {
                        "type": "Feature",
                        "properties": {
                                "mag": 0.8,
                                "place": "28 km SSE of Mina, Nevada",
                                "time": 1636270605062,
                                "updated": 1636270837488,
                                "tz": null,
                                "url": "https://earthquake.usgs.gov/earthquakes/eventpage/nn00827576",
                                "detail": "https://earthquake.usgs.gov/earthquakes/feed/v1.0/detail/nn00827576.geojson",
                                "felt": null,
                                "cdi": null,
                                "mmi": null,
                                "alert": null,
                                "status": "automatic",
                                "tsunami": 0,
                                "sig": 10,
                                "net": "nn",
                                "code": "00827576",
                                "ids": ",nn00827576,",
                                "sources": ",nn,",
                                "types": ",origin,phase-data,",
                                "nst": 8,
                                "dmin": 0.021,
                                "rms": 0.0637,
                                "gap": 173.62,
                                "magType": "ml",
                                "type": "earthquake",
                                "title": "M 0.8 - 28 km SSE of Mina, Nevada"
                        },
                        "geometry": {
                                "type": "Point",
                                "coordinates": [
                                        -118.0323,
                                        38.1455,
                                        3.2
                                ]
                        },
                        "id": "nn00827576"
                },
--More--

geometoryにkm単位の震源の深さがで格納されていました。 nullが格納されている項目が多いようです。

ogrinspectでgeojsonの中身を確認します。

$ python3 manage.py ogrinspect --srid=4326 all_day.geojson eq
# This is an auto-generated Django model module created by ogrinspect.
from django.contrib.gis.db import models


class eq(models.Model):
    id = models.CharField(max_length=0)
    mag = models.FloatField()
    place = models.CharField(max_length=0)
    time = models.BigIntegerField()
    updated = models.BigIntegerField()
    tz = models.CharField(max_length=0)
    url = models.CharField(max_length=0)
    detail = models.CharField(max_length=0)
    felt = models.IntegerField()
    cdi = models.FloatField()
    mmi = models.FloatField()
    alert = models.CharField(max_length=0)
    status = models.CharField(max_length=0)
    tsunami = models.IntegerField()
    sig = models.IntegerField()
    net = models.CharField(max_length=0)
    code = models.CharField(max_length=0)
    ids = models.CharField(max_length=0)
    sources = models.CharField(max_length=0)
    types = models.CharField(max_length=0)
    nst = models.IntegerField()
    dmin = models.FloatField()
    rms = models.FloatField()
    gap = models.FloatField()
    magtype = models.CharField(max_length=0)
    type = models.CharField(max_length=0)
    title = models.CharField(max_length=0)
    geom = models.PointField(srid=4326)

項目が多いだけあって長い、、、、

models.pyでデータベースのテーブルとカラムの要素を定義

map/ 以下にあるmodels.pyにogrinspectで調べた要素を追加します。 全部入れるとmodelの設定が大変なので、一部に絞りました。要素をcatで表示したところ、どの要素は必ず存在するようなので、null=Trueとします。また、文字列はCharFieldのmax_length=255としました。

from django.contrib.gis.db import models
class Eq_points(models.Model):
    id = models.CharField(primary_key=True,max_length=255)
    mag = models.FloatField(verbose_name='mag')
    place = models.TextField(verbose_name='place', null=True,blank=True)
    time = models.BigIntegerField(verbose_name='time')
    url = models.TextField(verbose_name='url')
    detail = models.TextField(verbose_name='detail')
    type = models.CharField(verbose_name='type',max_length=255, null=True,blank=True)
    title = models.TextField(verbose_name='title', null=True,blank=True)
    magtype = models.CharField(verbose_name='magtype',max_length=255, null=True,blank=True)
    geom = models.PointField(srid=4326)

    def __str__(self):
        return (self.id)

    class Meta:
        verbose_name = "EQ_points"
        verbose_name_plural = "EQ_points"

makemigrationsとmigrateを実行して、データベースにテーブルを作成します。

$ python3 manage.py makemigrations
$ python3 manage.py migrate

geojsonファイルをテーブルにセットする

manage.pyが存在するディレクトリに、load_eq.py というスクリプトを作成し、geojsonファイルをテーブルにセットします。

import os
from django.contrib.gis.utils import LayerMapping
from map.models import Eq_points

mapping = {
    "id"      : "id",
    "mag"     : "mag",
    "place"   : "place",
    "time"    : "time",
    "url"     : "url",
    "detail"  : "detail",
    "type"    : "type",
    "title"   : "title",
    "magtype" : "magType",
    "geom"    : "Point",
}


geojson_file= os.path.abspath(os.path.join(os.path.dirname(__file__), 'all_day.geojson'))

#Load
def run(verbose=True):
    lm = LayerMapping(Eq_points, geojson_file, mapping, transform=False, encoding='UTF-8')
    lm.save(strict=True, verbose=verbose)

djangoのシェルを使用して、テーブルにgeojsonをセットします。 load_eq.pyとgeojsonファイルは、map/以下に配置します。

# python3 manage.py shell
Python 3.8.10 (default, Sep 28 2021, 16:10:42)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from map import load_eq
>>> load_eq.run()
Saved: nn00827576
Saved: nc73649800
~~~~
(途中略)
~~~~
Saved: hv72784467
Saved: ak021e8tdxm1
>>>

Webでデータを確認する

djangoの管理画面で、ロードしたデータを表示できるようにします。 map/admin.py に定義したモデルと、adminにgisのモジュールを追加します。

# Register your models here.
from django.contrib.gis import admin
from . import models

admin.site.register(models.Eq_points, admin.OSMGeoAdmin)

あとは、djangoを起動して、ブラウザから管理画面にアクセスします。 以下のように表示されていれば成功です。

f:id:TTY6335:20211108220558p:plain

f:id:TTY6335:20211108220541p:plain

所感

geodjangoでGISデータベースを構築するより、postgisを導入したpostgresqlにgeodjangoにロードしていったほうが楽なような。API的な使い方をするにも、そのほうが自由度が大きい気がします... これで一応、GeoDjangoシリーズは終わりにします。

参考文献

MacOS上にGeodjango+PostGIS環境を構築 - Qiita

GeoDjango入門チュートリアル

Introduction - GeoDjangoではじめる地理空間情報