简体   繁体   中英

Flask - Listen to POST request

I'm using Flask in order to retrieve a coordinate value generated with javascript . Flask code:

from flask import Flask, request, session, g, redirect, url_for, abort, \
     render_template, flash, jsonify


@app.route('/geo', methods= ['GET', 'POST'])
def geo():
    return render_template('geo.html')


@app.route('/postmethod', methods = ['GET', 'POST'])
def get_post_location():
    where = request.form['location']
    return where

Console logs:

XHR finished loading: POST "http://127.0.0.1:5000/postmethod".

JAVASCRIPT :

<!DOCTYPE html>
<html>
  <head>
    <title>Geolocation</title>

    <meta charset="utf-8">

     <!--jquery-->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
    <style>
      /* Always set the map height explicitly to define the size of the div
       * element that contains the map. */
      #map {
        height: 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>

      function initMap() {
        var pos;
        var map = new google.maps.Map(document.getElementById('map'), {
          center: {lat: -34.397, lng: 150.644},
          zoom: 6
        });
        var infoWindow = new google.maps.InfoWindow({map: map});

        // Try HTML5 geolocation.
        if (navigator.geolocation) {
          navigator.geolocation.getCurrentPosition(function(position) {
            pos = {
              lat: position.coords.latitude,
              lng: position.coords.longitude
            };
            console.log(pos)

            infoWindow.setPosition(pos);
            infoWindow.setContent('You are here.');
            map.setCenter(pos);
          }, function() {
            handleLocationError(true, infoWindow, map.getCenter());
          });

          $.ajax({
            type: "POST",
            url: "/postmethod",

            // set content type header to use Flask response.get_json()
            contentType: "application/json",

            // convert data/object to JSON to send
            data: JSON.stringify({location: pos}),

            // expect JSON data in return (e.g. Flask jsonify)
            dataType: "json",

            // handle response
            success: function(response) {
                console.log(response);
            },
            error: function(err) {
                console.log(err);
            }
          });

        } else {
          // Browser doesn't support Geolocation
          handleLocationError(false, infoWindow, map.getCenter());

        }
      }

      function handleLocationError(browserHasGeolocation, infoWindow, pos) {
        infoWindow.setPosition(pos);
        infoWindow.setContent(browserHasGeolocation ?
                              'Error: The Geolocation service failed.' :
                              'Error: Your browser doesn\'t support geolocation.');
      }

    </script>
    <script async defer
    src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBr8V0XkaNFYkNXcP6eJc76b6YutvizwNw&callback=initMap">
    </script>
    <form action="/postmethod", method="post">
    </form>
  </body>
</html>

QUESTION :

how do I listen to this, so I can send where to some other script?

EDIT:

full traceback (after PJ's answer and I did get_json(silent=False)

127.0.0.1 - - [19/Mar/2017 23:20:26] "GET /geo HTTP/1.1" 200 -
data: {}
127.0.0.1 - - [19/Mar/2017 23:20:27] "POST /postmethod HTTP/1.1" 500 -
Traceback (most recent call last):
  File "/Library/Python/2.7/site-packages/flask/app.py", line 1836, in __call__
    return self.wsgi_app(environ, start_response)
  File "/Library/Python/2.7/site-packages/flask/app.py", line 1820, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "/Library/Python/2.7/site-packages/flask/app.py", line 1403, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/Library/Python/2.7/site-packages/flask/app.py", line 1817, in wsgi_app
    response = self.full_dispatch_request()
  File "/Library/Python/2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/Library/Python/2.7/site-packages/flask/app.py", line 1381, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/Library/Python/2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Library/Python/2.7/site-packages/flask/app.py", line 1461, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/Users/vitorpatalano/Documents/Code/Apps/App/app/app.py", line 134, in get_post_location
    where = data['location']
KeyError: 'location'

The issue is related to the way you are sending the data from javascript to Flask. The encoded "location" information is not a string value, but it an object, or JSON.

So, really what you're looking to do is send information (JSON) back and forth between Javascript & Flask

Here is how to accomplish this. Instead of the jQuery $.post() method you need to use the $.ajax() method directly.

UPDATE: Updating my code to a full working example on my local machine. The $.ajax() method was being called too early...needed to move it inside the scope of the call to the geolocation service.

Another thing to look into regarding chaining and managing the flow of asynchronous called is the Promise library.

Javascript/HTML:

<!DOCTYPE html>
<html>
<head>
    <title>Geolocation</title>
    <meta charset="utf-8">
    <!--jquery-->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
    <style>
        #map {height: 100%;}
        html, body {height: 100%;margin: 0;padding: 0;}
    </style>
</head>
<body>
    <div id="map"></div>
    <script>

    function initMap() {
        var pos = {},
            map = new google.maps.Map(document.getElementById('map'), {
                center: {lat: -34.397, lng: 150.644},
                zoom: 6
            }),
            infoWindow = new google.maps.InfoWindow({map: map});

        // Try HTML5 geolocation.
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(function(position) {
            pos = {
                lat: position.coords.latitude,
                lng: position.coords.longitude
            };

            infoWindow.setPosition(pos);
            infoWindow.setContent('Smells like coffee...');
            map.setCenter(pos);

            $.ajax({
                type: "POST",
                url: "/postmethod",
                contentType: "application/json",
                data: JSON.stringify({location: pos}),
                dataType: "json",
                success: function(response) {
                    console.log(response);
                },
                error: function(err) {
                    console.log(err);
                }
            });

            }, function() {
                handleLocationError(true, infoWindow, map.getCenter());
            });
        } else {
            // Browser doesn't support Geolocation
            handleLocationError(false, infoWindow, map.getCenter());
        }
    }

    function handleLocationError(browserHasGeolocation, infoWindow, pos) {
        infoWindow.setPosition(pos);
        infoWindow.setContent(browserHasGeolocation ?
        'Error: The Geolocation service failed.' :
        'Error: Your browser doesn\'t support geolocation.');
    }

    </script>
    <script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBr8V0XkaNFYkNXcP6eJc76b6YutvizwNw&callback=initMap">
    </script>
</body>
</html>

Within Flask you can now use the get_json() method which will reproduce the data structure you've encoded in javascript in python. You should use Flask jsonify() to return a response back to your javascript call.

Python:

@app.route('/postmethod', methods=['POST'])
def postmethod():
    data = request.get_json()
    print data
    return jsonify(data)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM