だいぶ前の記事で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を起動して、ブラウザから管理画面にアクセスします。 以下のように表示されていれば成功です。
所感
geodjangoでGISデータベースを構築するより、postgisを導入したpostgresqlにgeodjangoにロードしていったほうが楽なような。API的な使い方をするにも、そのほうが自由度が大きい気がします... これで一応、GeoDjangoシリーズは終わりにします。