2014-04-04 20 views
12

Sto scrivendo un sito basato su un piccolo flacone e vorrei inviare i dati dal client al server usando Ajax. Fino ad ora ho utilizzato solo le richieste Ajax per recuperare i dati dal server. Questa volta vorrei inviare i dati tramite la richiesta POST.Flask e Ajax Invia richieste 400

Questo è il ricevitore sul lato fiasco, ho ridotto a registrare appena un messaggio per evitare eventuali errori non necessari nell'ambito dell'attuazione di questo percorso:

@app.route("/json_submit", methods=["POST"]) 
def submit_handler(): 
    # a = request.get_json(force=True) 
    app.logger.log("json_submit") 
    return {} 

momento della presentazione della richiesta AJAX, fiasco me un dà 400 errore

127.0.0.1 - - [03/Apr/2014 09:18:50] "POST /json_submit HTTP/1.1" 400 - 

posso anche vedere questo nella console sviluppatore web nel browser

Perché pallone non chiamare submit_handler con i dati forniti nella richiesta?

var request = $.ajax({ 
    url: "/json_submit", 
    type: "POST", 
    data: { 
     id: id, 
     known: is_known 
    }, 
    dataType: "json", 
    }) 
    .done(function (request) { 
    }) 
+2

Stai usando la protezione CSRF da Flask-WTF per caso? Questo risponderà con un errore 400 se non includi il token CSRF nella richiesta AJAX. –

+0

quella era la soluzione.Se sei desideroso di una "risposta accettata", inseriscilo come tale e lo invierò in precedenza;) – wirrbel

+1

Ho ampliato quel commento in una risposta adeguata per te. :-) –

risposta

21

Se si utilizza il Flask-WTF CSRF protection avrete bisogno di esentare la visualizzazione o includono il token CSRF nella richiesta AJAX POST troppo.

esentare viene fatto con un decoratore:

@csrf.exempt 
@app.route("/json_submit", methods=["POST"]) 
def submit_handler(): 
    # a = request.get_json(force=True) 
    app.logger.log("json_submit") 
    return {} 

Per includere il token con richieste AJAX, interpolare il token nella pagina da qualche parte; in un'intestazione <meta> o nel codice JavaScript generato, quindi impostare un'intestazione X-CSRFToken. Quando si utilizza jQuery, utilizzare ajaxSetup hook.

Esempio utilizzando un meta tag (dalla documentazione Flask-WTF CSRF):

<meta name="csrf-token" content="{{ csrf_token() }}"> 

e nel codice JS da qualche parte:

var csrftoken = $('meta[name=csrf-token]').attr('content') 

$.ajaxSetup({ 
    beforeSend: function(xhr, settings) { 
     if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type)) { 
      xhr.setRequestHeader("X-CSRFToken", csrftoken) 
     } 
    } 
}) 

tuo gestore in realtà non inviare ancora i dati JSON ; è ancora una normale url-codificata POST (i dati finiranno nel request.form sul lato Flask); dovreste impostare il tipo di contenuto AJAX per application/json e utilizzare JSON.stringify() effettivamente presentare JSON:

var request = $.ajax({ 
    url: "/json_submit", 
    type: "POST", 
    contentType: "application/json", 
    data: JSON.stringify({ 
    id: id, 
    known: is_known 
    }), 
}) 
    .done(function (request) { 
}) 

e ora i dati possono essere accessibili come una struttura Python con il request.get_json() method.

Il parametro dataType: "json",-$.ajax è necessaria solo quando i tuoi vista rendimenti JSON (ad esempio, se usati flask.json.jsonify() per produrre una risposta JSON). Permette a jQuery di sapere come elaborare la risposta.

+1

Holy moly, grazie per la prima frase in questa risposta. Avevo esentato una vista (la forma principale) con '@ csrf.exempt', ma avevo dimenticato di aggiungere lo stesso decoratore alla mia vista' upload', che veniva chiamata tramite AJAX. Leggendo la prima frase in qualche modo spegni la lampadina :) – sofly

+1

Grazie! Aiutami molto. – sudoz

+1

Questo mi ha aiutato molto. Giusto punto. +1 per includere come inviare i dati indietro – tver3305

1

Potete provare come questo

var request = $.ajax({ 
    url: "/json_submit", 
    type: "POST", 
    contentType: "application/json", 
    data: JSON.stringify({ 
     id: id, 
     known: is_known 
    }), 
    dataType: "json", 
    }) 
    .done(function (request) { 
}) 

Prima di allora, Nel vostro codice restituisce oggetto dict. Non è corretto Esso restituisce JSON come

@app.route("/json_submit", methods=["POST"]) 
def submit_handler(): 
    # a = request.get_json(force=True) 
    app.logger.log("json_submit") 
    return flask.jsonify({'msg': 'success'}) 
Problemi correlati