2

I am building a webmap using GeoDjango, Leaflet and PostGIS. I am trying to write a function that returns a raster value from a database when the user clicks on the map (i.e., via a JS alert, or other means). I have read a number of posts on SE but can't seem to get the code to work myself.

The relevant code is below... first, the JS functions:

map.on('click', function(e) {
    var lng = e.latlng.lng;
    var lat = e.latlng.lat;
    console.log("I clicked!");
    resp = updateLatLng(lat, lng);
    console.log('The response is: ', resp);
});

function updateLatLng(lat, lng) {
    var data = {'lat': lat, 'lng': lng, csrfmiddlewaretoken: '{{ csrf_token }}'};
    $.post('{% url 'legend' %}', data);
    var response = '{{result}}';
    return response
};

The legend view in views.py is as follows:

def legend_view(request):

  lat = request.POST['lat']
  lon = request.POST['lng']

  query = "SELECT ST_Value(raster, ST_TRANSFORM(ST_SetSRID(ST_MakePoint(%s, %s), 4326), 4326)) FROM my_raster_layer;" % (lon, lat)

  conn = psycopg2.connect("dbname='mydb' user='postgres'")
  cur = conn.cursor()
  cur.execute(query)
  result = cur.fetchall()[0][0]

  print("\n\n++++++++++++\nInside the legend view\n")
  print("Lat: ", lat, "   Lon: ", lon)
  print("Value: ", result)
  print("++++++++++++\n\n")

  return HttpResponse(result)

When I click on the map, it successfully sends the lat and long values to views.py, as well as successfully queries the database. I can see this because it prints in the terminal I'm running the webmap from. However, it does not seem to be returning the value to the JS, as result is printing nothing.

Some other relevant SE items that I've followed, but can't get to work for my particular case:

  1. https://stackoverflow.com/questions/1445989/passing-python-data-to-javascript-via-django
  2. https://stackoverflow.com/questions/298772/django-template-variables-and-javascript?noredirect=1&lq=1
3
+50

I haven't used Django, but to my eyes it looks like your problem is with the concept of an AJAX call.

Using jQuery's $.post is an asycnhronous operation, so you can't work with it using a synchonous programming style (i.e. assigning the function's ouput to a variable).

Instead, you must supply a callback function which is exectued after the client recieves the server's response. Depending on how you want to display the data, you have a few different options.

Option 1

The best way, if you don't need to use the value for other operations in JavaScript, is to drop the value into your HTML with jQuery.

Option 2

If you want to use alert you can, but it's bad UX and I wouldn't reccommend it.

Option 3

Finally, if you need to actually work with the variable you can initialize a variable on page load, then assign the new value to that variable in the callback. This is probably more complicated than you need.

Option 4

The NEW best option (because I was bored) is probably to just use the Leaflet popup.

With some help from the jQuery docs:

// Initialize variable for use later
var theValue;
var popup = L.popup();

function updateLatLng(lat, lng) {
    var data = {'lat': lat, 'lng': lng, csrfmiddlewaretoken: '{{ csrf_token }}'};
    $.post('{% url 'legend' %}', data, function(resp) {
        // Option 1
        $("#raster-value").html("The value is: " + resp.result.value);            
        // Option 2
        alert("The value is: " + resp.result.value);
        // Option 3  -  Display the same way as Option 1, but you can
        //              do other stuff with it too.
        theValue = resp.result.value;
        $("#raster-value").html("The value is: " + theValue);
        // Option 4
        popup
          .setLatLng([lat, lng])
          .setContent('<pThe value is:<br />' + resp.result.value + '</p>')
          .openOn(map); // Obviously this assumes the map is initialized
    });
};

I would also suggest that you take a look at this SE post on returning AJAX responses from Django using JSON.

Hope this helps!

  • Thanks, this is helpful. I'm still unclear on how I would return that response, though. I just want to post that data upon clicking, and return a value from the database that I can then use within the JS script of my template. I've tried a variety of things in the callback function you suggest, but with no luck. – jbukoski Jun 25 '17 at 20:51
  • Can you post your template? Where are you actually trying to use the values? Does my function log something to your JS console? – nronnei Jun 25 '17 at 20:52
  • The template is quite large, but the JS functions I posted above are the relevant script portion. The function you gave does log the value to the console with console.log(resp.result);. I see you updated your post with a not about asynchronous operations... how do I assign the value to a variable that I can use elsewhere in the JS script? Ultimately I want to build a popup on the map with the data returned from the database. – jbukoski Jun 25 '17 at 21:01
  • 1
    Cool -- thanks a ton. This gets me over the hurdle I hit. SE says I can't award the bounty for another 19 hrs. Ping me if I don't in a few days time. And yes -- I'm using Leaflet's built in popups but also want to do some backend raster processing using PostGIS's functions, hence the need for dynamic extraction of data. – jbukoski Jun 25 '17 at 21:30
  • 1
    Cool, added a leaflet example for you to follow as well. This is all untested so let me know if something doesn't work and you find a solution; I'll fix it in my answer. – nronnei Jun 25 '17 at 21:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.