使用Flask-RESTful简化API开发

早上开始用Flask架设一个简单的API Server,中午把基本的GET请求处理完以后,发现按照我的方法处理POST、PUT、DELETE请求会很麻烦。刚好这个时候发现使用Flask扩展Flask-RESTful的话能大幅度简化API开发过程。

基本API

Table Here

API实现

具体的思路我在早上的那一片使用Flask实现一个RESTful API Server写的比较详细,刚兴趣可以翻开看看。使用扩展后,我直接按照官方档案中的Full Example基础上进行了修改调整。代码如下:

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
from flask import Flask,request
from flask.ext.restful import reqparse, abort, Api, Resource
from monitorDB import db,Piclist,User

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

#Deal with data form
parser = reqparse.RequestParser()
parser.add_argument('picid', type=int)
parser.add_argument('userid', type=int)
parser.add_argument('status', type=int)
parser.add_argument('username', type=str)
parser.add_argument('password', type=str)
parser.add_argument('email', type=str)

#get piclist
def getPiclist():
lim = request.args.get('limit', 10)
off = request.args.get('offset', 0)
results = Piclist.query.limit(lim).offset(off).all()

json_results = []
for result in results:
d = {'picid': result.id,
'picname': result.picname,
'time': result.time,
'status':result.status
}
json_results.append(d)

return json_results

#get userlist
def getUserlist():
lim = request.args.get('limit', 10)
off = request.args.get('offset', 0)
results = User.query.limit(lim).offset(off).all()

json_results = []
for result in results:
d = {'id': result.id,
'username': result.username,
'password': result.password,
'email':result.email
}
json_results.append(d)

return json_results

def abort_if_pic_doesnt_exist(picid):
if (Piclist.query.filter_by(id=picid).first() == None):
abort(404, message="Pic {} doesn't exist".format(picid))

def abort_if_user_id_doesnt_exist(userid):
if (User.query.filter_by(id=userid).first() == None):
abort(404, message="User {} doesn't exist".format(userid))

# Pic
# shows a single Pic item and lets you change or delete item
class pic(Resource):
def get(self, picid):
abort_if_pic_doesnt_exist(picid)
result = Piclist.query.filter_by(id=picid).first()
json_result = {'id': result.id,
'picname': result.picname,
'time': result.time,
'status':result.status
}

return json_result

def delete(self, picid):
abort_if_pic_doesnt_exist(picid)
result = Piclist.query.filter_by(id=picid).first()
db.session.delete(result)
db.session.commit()
return 204

def put(self, picid):
args = parser.parse_args()
status = args['status']
pic = Piclist.query.filter_by(id=picid).first()
pic.status = status
db.session.commit()
return 201

# shows a list of all piclist
class piclists(Resource):
def get(self):
return getPiclist()

# show a user
class user(Resource):

def get(self, userid):
abort_if_user_id_doesnt_exist(userid)
result = User.query.filter_by(id=userid).first()
json_result = {'id': result.id,
'username': result.username,
'password': result.password,
'email':result.email
}
return json_result

def delete(self, userid):
abort_if_user_id_doesnt_exist(userid)
result = User.query.filter_by(id=userid).first()
db.session.delete(result)
db.session.commit()
return 204

def put(self, userid):
abort_if_user_id_doesnt_exist(userid)
args = parser.parse_args()
user = User.query.filter_by(id=userid).first()
user.userid = userid
user.username = args['username']
user.password = args['password']
user.email = args['email']
db.session.add(user)
db.session.commit()
return 201

# shows a list of all Users
class userlists(Resource):
def get(self):
return getUserlist()

def post(self):
args = parser.parse_args()
user = User(args['username'],args['password'],args['email'])
db.session.add(user)
db.session.commit()
return 201

## Actually setup the Api resource routing here
api.add_resource(piclists, '/monitor/api/v1.0/piclist/')
api.add_resource(pic, '/monitor/api/v1.0/piclist/<int:picid>')
api.add_resource(userlists, '/monitor/api/v1.0/user/')
api.add_resource(user, '/monitor/api/v1.0/user/<int:userid>')

if __name__ == '__main__':
app.run(host='0.0.0.0',debug=True)

测试

GET请求可以直接通过浏览器来测试,但PUT、DELETE及POST请求需要使用Curl命令来测试

PUT请求

修改id为2的图片的status为3

1
2
3
4
5
6
7
8
MacBook-Pro:~ Eliyar$ curl -i -H "Content-Type: application/json" -X PUT -d '{"status":3}' http://192.168.1.199:5000/monitor/api/v1.0/piclist/2
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 4
Server: Werkzeug/0.10.1 Python/2.7.3
Date: Sat, 14 Mar 2015 13:54:09 GMT

201

POST请求

增加一位新用户

1
2
3
4
5
6
7
8
MacBook-Pro:~ Eliyar$ curl -i -H "Content-Type: application/json" -X POST -d '{"username":"newuser","password":"12345678","email":"freshman@eliyar.biz"}' http://192.168.1.199:5000/monitor/api/v1.0/user/
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 4
Server: Werkzeug/0.10.1 Python/2.7.3
Date: Sat, 14 Mar 2015 13:52:48 GMT

201

DELETE请求

删除ID为2的图片

1
2
3
4
5
6
7
8
MacBook-Pro:~ Eliyar$ curl -i -H "Content-Type: application/json" -X DELETE http://[hostname]/monitor/api/v1.0/piclist/2
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 4
Server: Werkzeug/0.10.1 Python/2.7.3
Date: Sat, 14 Mar 2015 13:54:09 GMT

201