Запросы на колбу и Ajax 400

Я пишу небольшой сайт на основе фляжки, и я бы хотел отправить данные от клиента на сервер с помощью Ajax. До сих пор я использовал только запросы Ajax для извлечения данных с сервера. На этот раз я хотел бы отправить данные через запрос POST.

Это приемник на стороне фляжки, я уменьшил его, чтобы просто записать сообщение, чтобы избежать лишних ошибок в реализации этого маршрута:

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

При отправке запроса ajax колба дает мне ошибку 400

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

Я также вижу это в консоли веб-разработчика в браузере

Почему флакон не вызывает submit_handler с предоставленными данными в запросе?

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

Ответ 1

Если вы используете защиту Flask-WTF CSRF, вам нужно либо освободить ваше мнение, либо включить токен CSRF в свой запрос POST AJAX.

Освобождение выполняется с помощью декоратора:

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

Чтобы включить токен с запросами AJAX, интерполируйте токен на страницу где-то; в заголовке <meta> или в сгенерированном JavaScript, затем установите заголовок X-CSRFToken. При использовании jQuery используйте ajaxSetup hook.

Пример использования метатега (из документации Flask-WTF CSRF):

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

и в вашем JS-коде где-нибудь:

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)
        }
    }
})

Ваш обработчик фактически не публикует данные JSON; он по-прежнему является регулярным url-закодированным POST (данные будут заканчиваться на request.form на стороне Flask); вам нужно установить тип содержимого AJAX на application/json и использовать JSON.stringify() для фактического представления JSON:

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

и теперь данные могут быть доступны как структура Python с помощью метода request.get_json().

Параметр dataType: "json", для $.ajax нужен только тогда, когда ваше представление возвращает JSON (например, вы использовали flask.json.jsonify() для создания ответа JSON). Он позволяет jQuery знать, как обрабатывать ответ.

Ответ 2

Можете ли вы попробовать как это

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

До этого в вашем коде возвращается объект dict. Это неверно. Он возвращает json как

@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'})