Flask,如何为ajax调用返回成功状态码

75

在服务器端,我只是将 JSON 格式的字典打印到控制台上。

@app.route('/',methods=['GET','POST'])
@login_required
def index():
    if request.method == "POST":
        print request.json.keys()
    return "hello world"

现在,每当我通过ajax进行post请求时,控制台都会打印出我需要的内容字典。

在客户端,我一直在尝试使用各种方法来执行一些基于jquery的操作,以响应成功的ajax调用。我刚意识到这可能是我的服务器端错误,即我没有发送任何请求头告诉jquery它的ajax调用已经成功。

那么,如何向我的客户端发送一个OK状态,告诉它一切都很好?

为了完整起见,这里是我的客户端代码:

$.ajax({
    type: 'POST',
    contentType: 'application/json',
    data: JSON.stringify(myData),
    dataType: 'json',
    url: '/',
    success: function () {
        console.log("This is never getting printed!!")
    }});

你尝试过返回一个有效的JSON字符串而不是纯文本“hello world”吗?你指定了返回数据类型为json,但jquery可能无法解码“hello world”,因此成功函数永远不会被调用。 - Peter Gibson
@PeterGibson,“hello world”在GET请求中被返回。我在POST请求中没有返回任何内容。 - yayu
1
@PeterGibson 那确实是问题所在。我加了一个 return 'OK' 现在它可以工作了。如果你愿意,你可以提交一个答案。 - yayu
1
哦,对不起 - 如果没有返回值,Python 默认返回 None,这不是一个有效的 JSON 对象。尝试返回类似于 '{"hello": "world"}' 的内容。 - Peter Gibson
好的,太棒了 :) 我现在明白 dataType 可能是用于提交数据的。 - Peter Gibson
6个回答

95

关于Flask中的响应:

关于响应

视图函数的返回值会自动转换为响应对象。如果返回值是字符串,则会将其转换为带有该字符串作为响应体、200 OK状态码和text/html MIME类型的响应对象。 Flask 将返回值转换为响应对象的逻辑如下:

  1. 如果已经是正确类型的响应对象,则直接返回。
  2. 如果是字符串,则创建响应对象,并使用默认参数。
  3. 如果返回一个元组,其中的项目可以提供额外信息。这样的元组必须具有形式为(response, status, headers)(response, headers)的格式,其中至少一个项目必须在元组中。 status值将覆盖状态码,而headers可以是附加标头值的列表或字典。
  4. 如果上述情况都不适用,则 Flask 假定返回值是一个有效的 WSGI 应用程序,并将其转换为响应对象。

因此,如果返回文本字符串(如您所做),则 AJAX 调用必须接收到200 OK状态码,并且成功回调函数必须执行。但是,我建议您返回格式化为 JSON 的响应,例如:

return json.dumps({'success':True}), 200, {'ContentType':'application/json'} 

60
作为aabilio答案的一个选项,你可以使用Flask中的jsonify方法,它会自动设置Content-Type:
from flask import jsonify

resp = jsonify(success=True)
return resp

您可以(可选)显式设置响应代码:

resp.status_code = 200

甚至更简单:return {} - Tomer

14

除了已经发布的答案之外,我发现在Flask中使用 make_response 方法(从版本0.6开始)尤其是当你需要在来自Flask的API的响应JSON中返回状态代码时,更清晰的选择:

from flask import Flask, jsonify, make_response

app = Flask(__name__)


@app.route('/do_thing')
def do_thing():
    # ... other code ...
    data = {'message': 'Done', 'code': 'SUCCESS'}
    return make_response(jsonify(data), 201)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)

此外,这种方法允许您传递响应代码(201),并将自动设置Content-Type标头为application/json


6
在较新的 Flask 版本中,它现在会自动处理响应中的转换。您可以简化响应,只需返回您的字典和响应代码,如下所示:
@app.route("/my_route")
def my_route():
    data = {"status": "success", "some key", "some value"}
    return data, 200

data 并不一定需要是一个字典,你也可以传入字符串!


1
谢谢,最简单的方式 - Abolfazl Rastgou

1
您也可以将response_class与json dump一起使用。请查看下面的示例:
from flask import Flask
from flask import json

app = Flask(__name__)

@app.route(/info)
def getInfo():
    response = app.response_class(
            response=json.dumps({"status":"success","code":0,"data":{"Name":"Eyong","Age":30}}),
            status=200,
            mimetype='application/json'
    )
    return response


1

当使用jsonify返回响应时,请将status_code作为return的第二个参数添加。我在此admin_required装饰器中使用了jsonify,并指定状态码为401(未授权)。示例:

return jsonify({'error': 'Admin access is required'}), 401

完整示例:

def admin_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        if current_user and hasattr(current_user, 'user_type') and current_user.user_type == 'admin':
            return f(*args, **kwargs)
        else:
            if '/api/' in request.url_rule.rule:
                return jsonify({'error': 'Admin access is required'}), 401

            flash(_('Admin access required'))
            return redirect(url_for('main.public_index'))

    return decorated

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接