Search code examples
javascriptjsondjangogoogle-maps-api-3geodjango

How to integrate Geodjango with Google Maps API 3?


I have a geodjango queryset containing several fields but want to use only user_name and location (a point field) which I want to use as a marker in google maps API 3.

Bear with me as I don’t know Javascript and I have a series of questions.
Take this as conceptual brainstorming for a novice:

  1. My SO search suggests that I need to serialize the queryset objects to JSON. I use the built-in serializer module to convert to JSON.
    I think the JSON objects are converted in views.py (let’s call it json_data). Are these JSON objects stored in the PostGIS database? Wouldn’t that be redundant?

  2. Furthermore, how do I reference them in the map.js (google maps API 3) javascript file?
    I want to (import?link?) JSON objects to display them as location markers.

  3. I want to know how to declare and iterate the javascript variable locations.

For var(i=0;i< locations.length;i++){[
[json_data.user_name, json_data.point],
]

var map = new google.maps.Map(document.getElementById('map'), {
  center: new google.maps.LatLng(49.279504, -123.1162),
  zoom: 14,
  mapTypeId: google.maps.MapTypeId.ROADMAP
});
var infowindow = new google.maps.InfoWindow();
var marker, i;
for (i = 0; i < locations.length; i++) {
  marker = new google.maps.Marker({
    position: new google.maps.LatLng(locations[i][1], locations[i][2]),
    map: map,
    icon: 'http://maps.google.com/mapfiles/ms/icons/blue-dot.png'
  });
  google.maps.event.addListener(marker, 'click', (function(marker, i) {
    return function() {
      infowindow.setContent(locations[i][0]);
      infowindow.open(map, marker);
    }
  })(marker, i));
}

Guide me if I went unnecessarily convoluted way to do a simple task.


Solution

  • TL;DR

    1. No, what you are doing is not redundant and nothing get's written to the database from those answers.
    2. You need to make a getJSON() or similar call to your API's endpoint to access the data.
    3. You can do it on the 2nd step's call and declare it as a list.

    What you are thinking is pretty much correct but there is room for improvement (thus the long answer below).


    Answer:

    Some time ago I read a very good initiation tutorial on building a GIS application with geodjango and google maps. Read it and it should give you a great jump start.

    After you read that we will follow a somewhat different way which leaves more room to play around with your front-end (use react for example or whatever comes to mind).

    The back-end:

    1. Create a view to retrieve the information you want (user_name, location) as JSON, using the values() queryset method which returns a list of dictionaries.
      Since we have to JSONify a list, we will use JsonResponse and we will mark it as unsafe:

      from django.http import JsonResponse
      
      def my_view(request):
          resp = MyModel.objects.all().values('user_name', 'location')
          return JsonResponse(list(resp), safe=False)
      
    2. Add an endpoint to access that view on urls.py:

      urlpatterns = [
          ...
          url(r'^my_endpoint/$', my_view, name='my_endpoint'),
          ...
      ]
      

      Now whenever we access the my_endpoint/ we will get a JSON representation of every object's user_name and location in our database which will look like this:

      [
        {user_name: a_user, location: [lat, lng]},
        {user_name: another_user, location: [lat, lng]},
        ...
      ]
      

    Moving to the front-end now:

    1. Make a getJSON() or an ajax() or any other type of call to the API and in the same time create a marker list (close to what @MoshFeu suggests):

      let map = new google.maps.Map(document.getElementById('map'), {
          center: new google.maps.LatLng(49.279504, -123.1162),
          zoom: 14,
          mapTypeId: google.maps.MapTypeId.ROADMAP
      });
      
      let markers = [];
      
      $.getJSON( "my_base_url/my_endpoint", function(data) {
          $.each(data, function() {
              markers.push(
                  new google.maps.Marker({
                      position: {
                          lat: data['location'][0], 
                          lng: data['location'][1]
                      },
                      map: map,
                      icon: 'http://maps.google.com/mapfiles/ms/icons/blue-dot.png'
                  })     
              );
          });
      });
      ...
      

    And we are pretty much done!

    You don't need to make any special serialization to your data.
    You can query the data from any type of front-end you can imagine which gives you designing freedom.