Flask not getting any data from jQuery request data

后端 未结 4 2021
無奈伤痛
無奈伤痛 2020-12-15 23:35

I\'ve a handler for a URL,

@app.route(\"/\", methods=[\'POST\'])
@crossdomain(origin=\'*\')
def hello():
    ss=str(request.data)
    print ss
    return ss
         


        
相关标签:
4条回答
  • 2020-12-15 23:49

    I have been working with similar functionality and after a bit of messing around with the ajax and python, this is what I came up with for python reading the ajax data

    JavaScript:

    var data = {
          data: JSON.stringify({
                            "value":'asdf'
                        })
       }
    };
    
    $.ajax({
       url:"/",
       type: 'POST',
       data: data,
       success: function(msg){
                  alert(msg);
                }
    })
    

    Python:

    from flask import json
    @app.route("/", methods=['POST'])
    def get_data():
        data = json.loads(request.form.get('data'))
        ss = data['value']
        return str(ss)
    
    0 讨论(0)
  • 2020-12-15 23:51

    Hmm, I get AJAX requests via request.form. I'm using DataTables and specify it like this:

    <script type="text/javascript">
    $(document).ready( function() {
            $('#mgmtdata').dataTable( {
                    "bServerSide": true,
                    "sAjaxSource": "{{url_for('.xhr')|safe}}",
                    "sServerMethod": "POST",
                    "bDeferRender": true,  
                    "bFilter": {{ info.filter if info.filter else "false" }},
                    "aoColumnDefs": [ {{ info.columndefs|safe if info.columndefs }} ],
            } );
    } );
    

    The xhr() function is simple:

    @usersview.route('/xhr', methods=["POST"])
    def xhr():
        if not 'usersview' in g:   
            g.usersview = UsersDatatableView()
        return g.usersview.render()
    

    usersview is an instance of the my Grid() object. In this case, it's only interesting on how it get's to the ajax data that DataTables sent in:

    def render(self):
        q = self.getQuery()
    
        # add filtering
        if 'sSearch' in request.form and request.form['sSearch']:
            q = self.applyFilter(q, request.form['sSearch'])
    
        # add sorting
        if 'iSortingCols' in request.form:
           # and so on
    
    0 讨论(0)
  • 2020-12-16 00:03

    interesting, as it turns out you can only use request.data if the data was posted with a mimetype that flask can't handle, otherwise its an empty string "" I think, the docs weren't very clear, I did some tests and that seems to be the case, you can take a look at the console output the flask generates when you run my tests.

    Incoming Request Data

    data
      Contains the incoming request data as string in case it came with a mimetype Flask does not handle.

    taken from http://flask.pocoo.org/docs/api/

    but since we are doing a standard POST using json flask can handle this quite well as such you can access the data from the standard request.form this ss=str(request.form) should do the trick as I've tested it.

    As a side note @crossdomain(origin='*') this seems dangerous, theres a reason why we don't allow cross site ajax requests, though Im sure you have your reasons.

    this is the complete code I used for testing:

    from flask import Flask
    app = Flask(__name__)
    
    from datetime import timedelta
    from flask import make_response, request, current_app
    from functools import update_wrapper
    
    
    def crossdomain(origin=None, methods=None, headers=None,
                    max_age=21600, attach_to_all=True,
                    automatic_options=True):
        if methods is not None:
            methods = ', '.join(sorted(x.upper() for x in methods))
        if headers is not None and not isinstance(headers, basestring):
            headers = ', '.join(x.upper() for x in headers)
        if not isinstance(origin, basestring):
            origin = ', '.join(origin)
        if isinstance(max_age, timedelta):
            max_age = max_age.total_seconds()
    
        def get_methods():
            if methods is not None:
                return methods
    
            options_resp = current_app.make_default_options_response()
            return options_resp.headers['allow']
    
        def decorator(f):
            def wrapped_function(*args, **kwargs):
                if automatic_options and request.method == 'OPTIONS':
                    resp = current_app.make_default_options_response()
                else:
                    resp = make_response(f(*args, **kwargs))
                if not attach_to_all and request.method != 'OPTIONS':
                    return resp
    
                h = resp.headers
    
                h['Access-Control-Allow-Origin'] = origin
                h['Access-Control-Allow-Methods'] = get_methods()
                h['Access-Control-Max-Age'] = str(max_age)
                if headers is not None:
                    h['Access-Control-Allow-Headers'] = headers
                return resp
    
            f.provide_automatic_options = False
            return update_wrapper(wrapped_function, f)
        return decorator
    
    
    
    @app.route("/", methods=['POST'])
    @crossdomain(origin='*')
    def hello():
        ss=str(request.form)
    
        print 'ss: ' + ss + ' request.data: ' + str(request.data)
        return ss
    
    
    @app.route("/test/")
    def t():
        return """
    <html><head></head><body>
    <script src="http://code.jquery.com/jquery.min.js" type="text/javascript"></script>
    <script type='text/javascript'>
    jQuery.ajax(
       {
          type: "POST",
          dataType: "json",
          data: "adasdasd",
        url: 'http://127.0.0.1:5000/',
    complete: function(xhr, statusText)
          {  alert(xhr.responseText) }})
    
    var oReq = new XMLHttpRequest();
    oReq.open("POST", "/", false);
    oReq.setRequestHeader("Content-Type", "unknown");
    oReq.send('sync call');
    alert(oReq.responseXML);
    </script></body></html>
    """
    
    if __name__ == '__main__':
        app.run()
    

    output:

    $ python test.py 
     * Running on http://127.0.0.1:5000/
    127.0.0.1 - - [07/Aug/2012 02:45:28] "GET /test/ HTTP/1.1" 200 -
    ss: ImmutableMultiDict([('adasdasd', u'')]) request.data: 
    127.0.0.1 - - [07/Aug/2012 02:45:28] "POST / HTTP/1.1" 200 -
    ss: ImmutableMultiDict([]) request.data: sync call
    127.0.0.1 - - [07/Aug/2012 02:45:28] "POST / HTTP/1.1" 200 -
    127.0.0.1 - - [07/Aug/2012 02:45:29] "GET /favicon.ico HTTP/1.1" 404 -
    

    and my system:

    $ python --version
    Python 2.6.1
    
    $ python -c 'import flask; print flask.__version__;'
    0.8
    
    $ uname -a
    Darwin 10.8.0 Darwin Kernel Version 10.8.0: Tue Jun  7 16:33:36 PDT 2011; root:xnu-1504.15.3~1/RELEASE_I386 i386
    

    using google chrome Version 20.0.1132.57

    0 讨论(0)
  • 2020-12-16 00:09

    This worked for me.

    In Javascript:

    $.ajax({
      type: 'POST',
      url: "enter your correct url",
      contentType: "application/json; charset=utf-8",
      data: JSON.stringify({title: 'My Title', article: 'My article'}),
      success: function(result){
        console.log(result)
      }
    });
    

    In Python (flask):

     from flask import request
     import json
    
     @app.route("/", methods=['POST'])
     def home():
       json_data = json.loads(request.data)
       print(json_data)
       return json_data
    

    NOTE: The points are;

    • JSON.stringify()
    • contentType: "application/json; charset=utf-8"
    • json.loads
    • request.data
    0 讨论(0)
提交回复
热议问题