geodjango実装メモ(修正版)
コンテンツ
- PointField等のGeo系特有のFieldを使うには?
- admin(管理ページ)でGeoデータを編集するためには?
- geometry型のデータをどのように画面に表示するか?
- django leafletの使い方
- 半径10km以内のpointのみを表示するにはどうすれば実現できるか?
- models.GeoManager()について
- wktを使ってオブジェクトをどう作成するのか?
留意点
このページに記録しているのはgeodjangoの内容が主であり、djangoにOSMを表示するためのjavascriptライブラリleafletやdjango用サードパーティモジュールdjango leafletを使う際のメモは別ページに記載する。
1. PointField等のGeo系特有のFieldを使うには?
models.pyでpointを使う場合はmodels.PointFieldを使う。しかしデフォルトの from django.db import models にはPointFieldがない。
from django.contrib.gis.db import models
上記を使うとPointFieldを始めとしたgeometry型のデータを格納することができる。
Geo系特有のFieldをModelに導入する際のサンプル資料
GeoDjango Model API | Django documentation | Django
2. admin(管理ページ)でGeoデータを編集するためには?
adminでも他のモデルインスタンスと同じようにGeoデータを編集する事ができる。
これも同様にadmin.pyでデフォルトのfrom django.contrib import adminを使わない。
from django.contrib.gis import admin
上記のadminモジュールを使うことでadmin画面で空間データの入力が可能になる。 注意点としては上記のadminのインポートは、admin.pyに使うことはもちろん、urls.pyにも使う点だ。 デフォルトで生成さるproject用のurls.pyにはfrom django.contrib import adminが使ってある。つまり、これも修正すること。
from django.contrib.gis import admin # これに変更すること from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('maps/', include(maps.urls)), ]
3.geometry型のデータをどのように画面に表示するか?
普段どおり書くと...
いつも通りにdjangoのtemplate,viewを書いてもgeometry型データは文字としてしか表示されない。
つまりテンプレートに表示させるには何らかの処理が必要になる。それが何かを明らかにする必要がある。
ブラウザでGeoデータをマッピングするには
ブラウザでデータをマップにプロットする場合にはdjango leafletを使う。
そもそもleafletはjavascriptのライブラリのようである。django leafletはそのdjnagoバージョンらしい。
マッピングするにはdjango leafletが必要だ!という旨の資料
Displaying a map in a Django Webapp (2/3): Develop a GIS webapp with GeoDjango
django leafletのドキュメント
Welcome to Django Leaflet’s documentation! — Django Leaflet 0.20 documentation
4. django leafletの使い方
内容が結構あるので以下に別途作成した。
django leaflet の使い方メモ - diadia
5. 半径10km以内のpointのみを表示するにはどうすれば実現できるか?
postgisであれば、そのSQLを実行すればそのデータを抽出できる。
大体postgisのSQLの書き方とGeodjangoのクエリメソッドは似ていることがあるのでそこから見当をつけられる。
Distance Queriesがある。
GeoDjango Database API | Django documentation | Django
クエリメソッド | 説明 | URL |
---|---|---|
distance_lt | ルックアップジオメトリからジオメトリフィールドまでの距離が指定された距離値よりも小さいモデルを返します。 | GIS QuerySet API Reference | Django documentation | Django |
distance_lte | ルックアップジオメトリからジオメトリフィールドまでの距離が指定された距離値以下であるモデルを返します。 | GIS QuerySet API Reference | Django documentation | Django |
distance_gt | ルックアップジオメトリからジオメトリフィールドまでの距離が、指定された距離値よりも大きいモデルを返します。 | GIS QuerySet API Reference | Django documentation | Django |
distance_gte | ルックアップジオメトリからジオメトリフィールドまでの距離が、指定された距離値以上であるモデルを返します。 | GIS QuerySet API Reference | Django documentation | Django |
dwithin | ルックアップジオメトリからジオメトリフィールドまでの距離が互いに指定された距離内にあるモデルを返します。 ターゲットジオメトリが投影システムにある場合にのみ、距離オブジェクトを提供できることに注意してください。 地理的なジオメトリの場合、ジオメトリフィールドの単位(WGS84の度数など)を使用する必要があります。 | GIS QuerySet API Reference | Django documentation | Django |
メモ:https://codeday.me/jp/qa/20190526/901886.html
https://docs.djangoproject.com/en/2.2/ref/contrib/gis/db-api/#distance-lookups
6. models.GeoManager()について
どうやらGeoManager()はdjango2.0以降では使われていないようだ。 Spatial Lookupsを使うこととある。
GeoManagerはdjango2.0以降使われないことに言及した資料
Django has no attribute 'GeoManager' issue - Stack Overflow
django2.0で削除された機能を示すドキュメント
Django 2.0 release notes | Django documentation | Django
7. wktを使ってオブジェクトをどう作成するのか?
WKT, HEX, WKB, GeoJSONを使ってGEOSGeometryオブジェクトを作成することができる。例えばwktならばGEOSGeometryの引数としてwktを使うだけで生成する事ができる。
from django.contrib.gis.geos import GEOSGeometry point = GEOSGeometry('POINT(5 23)') # WKT
ただし、sridは上記の場合は設定されないので別途自分で設定する必要がある。
print(point.srid) >>>None
point = GEOSGeometry('POINT(5 23)', srid=4326) #または point = GEOSGeometry('POINT(5 23)') point.srid = 4326 #または point = GEOSGeometry("SRID=4326;POINT(5 23)")
GEOSGeometryオブジェクトは、そのままgeogjangoの操作に利用することができる。 例えばgeogjangomのあるモデルオブジェクトのポリゴン内にGEOSGeometryオブジェクトのPOINTが含まれるかなんてことができる。
point = GEOSGeometry('POINT(5 23)', srid=4326) city = City.objects.get(name="鹿児島") city_polygon = city.geom print(city_polygon.contains(point)) >>>False
geodjangoのfieldに対しそのまま使用する事ができるか?