Search by

    GeoDjangoのデータをGoogleMapに表示する方法

    djangoのポリゴンデータをgooglemap上に描画する方法について

    今回やること

    GeoDjangoチュートリアルの解説の続きです。

    前回やったことは...
    • DBを拡張して地理データを扱えるように
    • shapファイルから、DBへデータインポート
    • adminサイトでデータのポリゴンデータの確認
    今回すること
    • 自作のView,template上で、googlemapにdjangoから取得したポリゴンデータを描画する

    django emoji-left_right_arrow geojson emoji-left_right_arrow google maps api

    djangoとgoogle maps apiはgeojsonという形式でやり取りできる。 この記事では、django側の出力の方法と、google maps api側の受け取り方を書いています。

    まずはソース

    Views
    world/views.py
    from django.core.serializers import serialize
    from django.http import HttpResponse
    from .models import WorldBorder
    from django.views.generic import TemplateView
    
    # 地図の下地 クラスの中で何も実装していないので、urls.pyでtemplate指定するだけでもよい
    class MapView(TemplateView):
        template_name="world/index.html"
    
    def api_get_worldborder(request):
        # シリアライザを使って、ポリゴンデータをgeojsonに変換する。
        worldborder = serialize('geojson', WorldBorder.objects.all(), geometry_field='mpoly')
        # geojsonを出力する
        return HttpResponse(worldborder, content_type='application/json')
    URLs
    world/urls.py
    urlpatterns = [
      # 下地
       path('', views.MapView.as_view(), name='world_index'),
      
      # ポリゴンデータ呼ぶとこ
       path('api/', views.api_get_worldborder),
    ]
    template
    templates/world/index.html
    <!DOCTYPE html>
    <html>
      <head>
        <title>Simple Map</title>
        <meta name="viewport" content="initial-scale=1.0">
        <meta charset="utf-8">
    
        <style>
          /* Always set the map height explicitly to define the size of the div
           * element that contains the map. */
          #map {
            height: 430px;
            width: 100%;
          }
          /* Optional: Makes the sample page fill the window. */
          html, body {
            height: 100%;
            margin: 0;
            padding: 0;
          }
        </style>
      </head>
      <body>
        <div id="map"></div>
    
        <script>
          var map;
          function initMap() {
            map = new google.maps.Map(document.getElementById('map'), {
              center: {lat: 34.397, lng: 150.644},
              zoom: 2
            });
    
            // これだけでポリゴンのデータレイヤーを作れる。簡単。
            map.data.loadGeoJson('/api/');
    
            // スタイルの指定
            map.data.setStyle({
                fillColor: 'pink',
                strokeColor: 'blue',
                strokeWeight: 1
            });
    
          }
        </script>
    
        <script src="https://maps.googleapis.com/maps/api/js?key='YOUR API KEY'&callback=initMap"
        async defer></script>
      </body>
    </html>

    簡単な例だと上記だけで実現できる。 こんな感じで国境が表示された。 ただし、データが重いので、描画に時間かかる。 worldborder0


    この状態で、adminサイトでポリゴンを追加したら worldborder1


    リロードすると、ちゃんと表示される。oh...super...emoji-open_mouth worldborder

    今後やりたいこと

    jsから map.data.loadGeoJson();する時に、getのパラメータを指定したり、
    一回のデータ受信量を制御したりできると、実用的なアプリっぽくなりそうだ。

    jqueryでこの辺りを実装すると、どうしても逐次的になってしまうので、そろそろフロントエンド本格的に書ける技術がほしい。

    この機能を追加している時に、djangoのrestframeworkに触れた。今回使わなかったけど。

    まずはバックエンドを実装できるようになるemoji-fist

    参考公式ページ

    datalayerについてのあれこれ

    ソースコード

    github