Flask API

Flask API

给大家分享一下flask apiFlask-RESTful API 的两种不同用法。。首先API只会返回json的类型,不会返回HTML。API一般适用于前后端分离的情况。Flask API的实现方式有两种。第一种就是不用flask_restplus。第二种是用flask_restplus。首先给大家说一下不用flask_restplus怎么写。

不使用 flask_restplus

在不适用flask_restplus的情况下我们可以直接使用route的形式来写API。只是把return render_template改成了return jsonify 来返回一个json类型的数据。可以根据不同的request的方式(GET, POST, DELETE)可以处理不同的事情,比如DELETE可以用来删除数据, POST可以添加数据,GET可以获取数据。具体实现方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from flask import Flask, request, jsonify

app = Flask(__name__)

# SECRET_KEY 可以设置为任意的string
app.config["SECRET_KEY"] = "WHATEVER"


@app.route('/index', methods=["POST","GET","DELETE"])
def index():
if request.method == "GET":
username = request.args.get("username")
return jsonify({"GET": username})
if request.method == "POST":
username = request.args.get("username")
return jsonify({"POST": username})
if request.method == "DELETE":
username = request.args.get("username")
return jsonify({"DELETE": username})

app.run(debug=True)

GET 请求测试如下:

1
curl -X GET "http://127.0.0.1:5000/index?username=admin" -H "accept: application/json"

结果如下:

1
2
3
{
"GET": "admin"
}

POST 请求测试如下

1
curl -X POST "http://127.0.0.1:5000/index?username=admin" -H "accept: application/json"

结果如下:

1
2
3
{
"POST": "admin"
}

DELETE 请求测试如下

1
curl -X DELETE "http://127.0.0.1:5000/index?username=admin" -H "accept: application/json"

结果如下:

1
2
3
{
"DELETE": "admin"
}

使用flask_restplus

Flask-RESTful 提供了 reqparse 一种类似 argparse 参数解析机制以简化参数处理。所以处理请求数据的时候和Flask不太一样。parser = reqparse.RequestParser(): reqparse使用RequestParser() 可以从 flask.Request.values,以及 flask.Request.json 解析值。这里创建了一个解析对象parser。parser.add_argument('task'):向parser对象中添加你要关注的命令行参数和选项,每一个add_argument方法对应一个你要关注的参数或选项。parser.parse_args():调用parse_args()方法进行解析,解析成功之后即可使用。POST, GET, DELETE获取参数的方式一样。在定义API的时候可以是用@api.param添加参数,在web端测试的时候比较方便。@app.doc(description='xx')添加对这个API的描述。@app.response(200,'success')定义路由code的信息,普遍是用的是200,404,400,403等等。

我发现最近flask的版本稳定性很差,尤其是werkzeug和flask之间的版本冲突,大家最好用虚拟机进行测试实验比较好。。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
from flask import Flask, jsonify, make_response, request
from flask_restplus import Api, reqparse, abort, Resource

app = Flask(__name__)
api = Api(app)

app.config['SECRET_KEY'] = 'WHATEVER'

@api.route('/login')
@api.param('username')
@api.doc(description="This is test")
@api.response(200, 'Success')
class Login(Resource):

@staticmethod
def post():
parser = reqparse.RequestParser()
parser.add_argument('username', type=str)
args = parser.parse_args()
username = args.get("username")

# 如果结果正确可以直接make_response
# 如果不正确可以用abort
if username == "admin":
return make_response(jsonify({"POST": username}),200)
else:
abort(400, "username not currect")

@staticmethod
def get():
parser = reqparse.RequestParser()
parser.add_argument('username', type=str)
args = parser.parse_args()
username = args.get("username")

if username == "admin":
return make_response(jsonify({"GET": username}),200)
else:
abort(400, "username not currect")

app.run(debug=True)

GET 请求测试:

API的请求方法和flask不太一样,需要 -d 加上参数, POST请求也是一样

1
curl -X GET "http://127.0.0.1:5000/login" -H "accept: application/json" -d "username=admin"

请求结果:

1
2
3
{
"GET": "admin"
}

POST 请求测试:

1
curl -X POST "http://127.0.0.1:5000/login" -H "accept: application/json" -d "username=admin"

请求结果:

1
2
3
{
"POST": "admin"
}

给大家看一下abort的显示结果:

1
2
3
{
"message": "username not currect"
}

或者大家可以直接打开http://127.0.0.1:5000可以显示界面来测试。 如下图所示:

前端请求API

昨天写的太晚就先睡了,今天给补上怎么用AJAX也就是前端来请求API数据的。大家可以自行了解一下AJAX的function什么的,demo用的是JQuery中的AJAX。因为牵涉到了跨域请求,所以后端也稍微有一点改变。需要用到flask_cors来解决这个问题。只需要在上面的Python代码加两行代码就OK了。

1
2
3
4
from flask_cors import CORS
...... # 这些是初始化app部分
CORS(app)
......

如果不加CROS(app)的话会在浏览器的调试Console出现以下报错:

1
Access to XMLHttpRequest at 'http://127.0.0.1:5000/login?username=admi' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

前端代码具体实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script type="text/javascript">
$.ajax ({
url: 'http://127.0.0.1:5000/login',
data: {
username: "admin"
},
error: function(data) {
// data 包含了整个的错误信息
// data.status 指的是返回的错误代码,比如400
// data.responseJSON.message 指返回的错误信息, username not currect
console.log("ERROR: ", data)
},
success: function(data) {
console.log(data)
},
type: "GET"
});
</script>

拓展

当我们有多个api功能需要实现,比如登录,注册等等。为了更好的区分每个功能之间的url,我们可以使用api.namespace()对不同功能创建不同的变量。比如我们需要实现注册,登录(验证模块)时我们可以使用auth = api.namespace('auth', description="Authentication Services")。同时为了能更加方便的在api提供的接口里面进行测试,我们可以对每个method进行声明responseparam 或者doc等等。比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from flask import Flask, jsonify, make_response, request
from flask_restplus import Api, reqparse, abort, Resource

app = Flask(__name__)
api = Api(app)

app.config['SECRET_KEY'] = 'WHATEVER'

auth = api.namespace('auth', description="Authentication Services")

@auth.route("/login", strict_slashes=False)
class Login(Resource):

@auth.response(200, 'Success')
@auth.response(400, 'Missing args')
@auth.response(403, 'Not register')
@auth.param('password', 'Password')
@auth.param('username', 'Username')
@auth.doc(description="Please enter username and password. "
"If the username and password correct, a token will be returned")
def post(self):
username = get_request_args("username", str)
password = get_request_args("password", str)


return make_response(jsonify(username=username,password=password), 200)

app.run(debug=True)

为了方便使用,我创造了一个公开的轻量级API模板

----- End Thanks for reading-----