[GIS] Display GeoJSON data on map using django-leaflet

geodjangoleaflet

I want to display GeoJSON data on map in geodjango.

When I use the below code only GeoJSON data like:

{
  "type": "FeatureCollection",
  "features": [{
        "type": "Feature",
        "properties": {
          "model": "pft.pft"
        },
        "id": 1,
        "geometry": {
          "type": "Point",
          "coordinates": [76.996944, 31.58]
        }
      }, {
        "type": "Feature",
        "properties": {
          "model": "pft.pft"
        },
        "id": 2,
        "geometry": {
          "type": "Point",
          "coordinates": [76.670778, 31.487083]
        }
      }, {
        "type": "Feature",
        "properties": {
          "model": "pft.pft"
        },
        "id": 3,
        "geometry": {
          "type": "Point",
          "coordinates": [77.253, 30.651722]
        }
      },

is getting displayed on my webpage, but I want to display it on map.

template/map.html

{% load leaflet_tags %}
<html>
<head>
    {% leaflet_js %}
    {% leaflet_css %}
    <!--  <script src="OpenLayers.js" type="text/javascript"></script> -->

<style>
header {
    background-color:black;
    color:white;
    text-align:center;
    padding:5px;     
}
nav {
    line-height:30px;
    background-color:#eeeeee;
    height:503px;
    width:240px;
    float:left;
    padding:5px;          
}
section {
    width:579px;
    float:left;
    padding:10px;   
    height:494px;
}
footer {
    background-color:black;
    color:white;
    clear:both;
    text-align:center;
    padding:5px;         
}
</style>
</head>
    <body>
    {% leaflet_map "main" callback="main_map_init" %}
    <header>
    <h2>Plant Functional Types</h2>
    </header>
<nav>
<a href="{% url 'geojson_provinces'%}"><button type="button" onclick=>Actual plant functional type</button> 
<button type="button" >Potential plant functional type</button>
<button type="button" > Plant functional types likely to change</button>
<a href="{% url 'add_multiple_accounts' %}"><button type="button" > Upload species data</button></a>
</nav>

<div id="map" class="map" style="width:1080px; height:512px;float:right;" ></div>
<script type="text/javascript">
     function main_map_init (map, options) {

    var dataurl = '{% url "data" %}';
    // Download GeoJSON via Ajax
    $.getJSON(dataurl, function (data) {
        // Add GeoJSON layer
        L.geoJson(data).addTo(map);
    });

}

</script>
<footer>
</footer>
       </body>
</html>

views.py

def geojson_provinces(request):
    conn = psycopg2.connect(dbname="geodjango",host='localhost',user='postgres', password='postgres', port=5433)
    dict_cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
    cur=conn.cursor()
    res = dict_cur.execute("SELECT ST_AsGeoJson(geom) AS json FROM pft_pft LIMIT 10;")

    points=dict_cur.fetchall()
    print (points)
    json_res  = []
    for row in points:
        json_obj  = row['json']
        print (json_obj)
        json_res.append(json_obj)
        print(json_res)
    #json = simplejson.dumps(data)

    dict_cur.close()
    data = {'geojson':  mark_safe(json_res)}
    return render(request, 'map.html', data)

urls.py

 url(r'^data/$', GeoJSONLayerView.as_view(model=PFT), name='data'),

models.py

class PFT(models.Model):
    species=models.CharField(max_length=50)
    # GeoDjango-specific: a geometry field (MultiPolygonField)
    geom = models.PointField(srid=4326)
    objects=models.GeoManager()
    # Returns the string representation of the model.
    def __str__(self):              # __unicode__ on Python 2
        return '%s %s %s' % (self.species, self.geom.x, self.geom.y)

How to solve this?

Best Answer

change your Views.py file in your app

#views.py
from django.shortcuts import render
from django.views.generic import TemplateView
from django.core.serializers import serialize
from django.http import HttpResponse
from .models import County

# Create your views here.

class HomePageView(TemplateView):
    template_name='index.html'  #the template name in template folder


#state dataset

def state_datasets(request):
    state=serialize('geojson',State.objects.all()) #converts the shapefile loaded to geojson
    return HttpResponse(state,content_type='application/json')

#beat dataset


def beat_datasets(request):
    beat=serialize('geojson',Beat.objects.all()) #converts the shapefile loaded to geojson
    return HttpResponse(beat,content_type='application/json')

Add the following to your urls.py file

#urls.py

from django.conf.urls import url
from djgeojson.views import GeoJSONLayerView
from .views import HomePageView,beat_datasets,state_dataset




urlpatterns=[
    url(r'^$',HomePageView.as_view(),name='home'),
    url(r'^state_data/$',state_datasets,name='state') #state url
    url(r'^beat_data/$',beat_datasets,name='beat') #the url beat
]

Make sure you add this line below in your setting at the template:

'DIRS': [os.path.join(BASE_DIR,'templates')],

Then create a templates folder with index.html file:

#index.html

<!DOCTYPE html>
<html lang="en">

{% load static %}
{% load leaflet_tags %}

<head>

    {% leaflet_js %}
    {% leaflet_css %}
   
    <title>map</title>
  
<style>
    #gis{
        width:76%;
        height:550px;
    }
</style>

   <script src="{% static 'ajax/leaflet.ajax.js' %}"></script>
   

</head>

<body>
          <script>
                function our_layers(map,options){

                    // adding open street map

                    var osm = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}{y}{x}.png');
                    // loading state geojson

                    var state = new L.GeoJSON.AJAX("{% url 'state' %}",{

                    });
                    state.addTo(map);

                     var beat = new L.GeoJSON.AJAX("{% url 'beat' %}",{

                    });
                    beat.addTo(map);


                }
        </script>

   {% leaflet_map "gis" callback="window.our_layers" %}

</body>
</html>

Make sure you have leaflet ajax plugin ,django-leaflet (pip install django-leaflet)