本篇博客参考自官方文档:Quickstart 。
一个demo 首先,安装flask_restful包:
1 pip3 install flask_restful
然后请看代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 from flask import Flaskfrom flask_restful import Resource, Apiapp = Flask(__name__) api = Api(app) class HelloWorld (Resource ): def get (self ): return { 'hello' : 'world' } api.add_resource(HelloWorld, '/' ) if __name__ == '__main__' : app.run(debug=True )
然后运行:
访问接口:
1 curl http://127.0.0.1:5000
然后能得到响应:
多方法 flask_restful能够使用多方法,如:get, post, put, delete。 那么下面是代码,一看就明白:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 from flask import Flask, requestfrom flask_restful import Resource, Apiapp = Flask(__name__) api = Api(app) todos = {} class TodoSimple (Resource ): def get (self, todo_id ): return {todo_id: todos[todo_id]} def post (self, todo_id ): todos[todo_id] = request.form['data' ] return {todo_id: todos[todo_id]} api.add_resource(TodoSimple, '/<string:todo_id>' ) if __name__ == '__main__' : app.run(debug=True )
以下是用不同的方法请求接口返回的响应:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 curl http://localhost:5000/111 -d "data=Remember the fire" -X POST { "111" : "Remember the fire" } curl http://localhost:5000/111 { "111" : "Remember the fire" }
返回不同的响应码:
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 from flask import Flask, requestfrom flask_restful import Resource, Apiapp = Flask(__name__) api = Api(app) class Todo1 (Resource ): def get (self ): return { 'task' : 'Hello World' } class Todo2 (Resource ): def get (self ): return { 'task' : 'hello world' }, 201 class Todo3 (Resource ): def get (self ): return { 'task' : 'Hello world' },201 ,{ 'Etag' : 'some-opaque-string' }
多个路由指向一个视图 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 from flask import Flask, requestfrom flask_restful import Resource, Apiapp = Flask(__name__) api = Api(app) class Hello (Resource ): def get (self ): return { 'msg' : 'good' } api.add_resource(Hello, '/' , '/hello' ) if __name__ == '__main__' : app.run(debug=True )
这段代码执行后,无论是访问/,还是访问/hello,得到的响应都会是’msg’: ‘good’。
参数解析 如果不明白”参数解析”是什么意思的话,就将其当成验证参数就好。 使用flask_restful中的一个方法,可以判断参数的类型,如果参数的类型不对,就返回一个自定义的提醒。 那么下前请看代码:
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 from flask import Flask, requestfrom flask_restful import Resource, Api, reqparseapp = Flask(__name__) api = Api(app) parser = reqparse.RequestParser() parser.add_argument('rate' , type =int , help ='Rate to charge for this resource' ) class Hello (Resource ): def get (self ): return { 'msg' : 'good' } def post (self ): args = parser.parse_args() return { 'msg' : 'good' } api.add_resource(Hello, '/hello' ) if __name__ == '__main__' : app.run(debug=True )
运行服务,访问接口,这里要注意我携带的参数:
1 2 curl -d 'rate=foo' http://127.0 .0 .1 :5000 /hello
得到的响应,这个响应有点怪,因为官方文档里还带了一个status:400,我的响应如下:
1 2 3 4 5 6 7 8 { "message" : { "rate" : "Rate to charge for this resource" } } {'status' : 400, 'message' : 'foo cannot be converted to int' }
这个响应就是我之前自定义的那个提醒,因为我设置的type为int类型,而’foo’明显是字符串,不是我所指定的类型,因此返回了提醒。 接下来再用int类型的参数请求一次:
1 2 curl -d 'rate=1' http://127.0 .0 .1 :5000 /hello
成功得到响应:
数据格式化 这一内容的主要目的是返回一个对象。官方文档上只给出了代码,而且还不是全部代码,没有给出运行结果,就连名为”Full Example”标题下的内容里都没有与”Data Formatting”(数据格式化),这让理解能力奇差的我感到十分的难过。不过好在按照官方文档的代码写还是成功了。
最后我再放全部代码,那么接下来是第一步:导入模块。
1 from flask_restful import fields, marshal_with
看字面意思就知道,fields是字段的意思,不过这个marshal_with就让人有点难以理解了,但是不急,官方文档上说明了,这是个装饰器,而关于fields的作用,官方文档上是这么说的:”you use the fields module to describe the structure of your response.”,用我的垃圾英语来翻译的话,就是”使用字段模块来描述响应的结构体”。这个其实和Django的ORM差不多,那么我们先看代码。
1 2 3 4 resource_fields = { 'task' : fields.String, 'uri' : fields.Url('todo_ep' ) }
task是一个字符串类型的字段,而uri是一个路由的endpoint参数,当然这些都不是死的,你也可以把uri改成uriii,这没有什么问题。如果这个endpoint不存在,即fields_Url(‘todo_ep’)中的值不存在,那么在运行Flask的时候会报错。如果你没有给路由设置endpoint,那么该路由的endpoint名称默认为该路由的视图名,也就是类名。你需要将其替换成你的视图名。下面来一段代码讲一下:
1 2 3 class Todo (Resource ): pass api.add_resource(Todo, '/' )
其中/的endpoint参数,即指向Todo视图的endpoint参数,其值为’todo’。 而如果你这么写的话:
1 2 3 class Todo (Resource ): pass api.add_resource(Todo, '/' , endpoint="fire" )
那么你上面的fields.Url()的参数应该为’fire’,即fields.Url(‘fire’)。 当然,如果你认为麻烦,这个字段不写也是可以的,它其实就是一个路由的地址。 那么下面,我们首先定义一个类:
1 2 3 4 5 6 7 class TodoDao (object ): def __init__ (self, todo_id, task ): self.todo_id = todo_id self.task = task self.status = 'active'
这个类是用来接受参数的,不过实际响应的数据还是得看上面的定义的那个字典。
当然,一切还是以实践为主,所以下面我们贴上全部代码:
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 from flask import Flask, requestfrom flask_restful import Api, fields, marshal_with, Resourceapp = Flask(__name__) api = Api(app) resource_fields = { 'todo_id' : fields.String, 'task' : fields.String, } class TodoDao (object ): def __init__ (self, todo_id, task ): self.todo_id = todo_id self.task = task self.status = 'active' class Todo (Resource ): @marshal_with(resource_fields ) def get (self, **kwargs ): return TodoDao(todo_id='my_todo' , task='Remeber the milk' ) class ToBeBetter (Resource ): @marshal_with(resource_fields ) def get (self, **kwargs ): return TodoDao(todo_id='my_todo' , task="Remeber Me." ) api.add_resource(Todo, '/' ) api.add_resource(ToBeBetter, '/better' ) if __name__ == '__main__' : app.run(debug=True )
那么接下来运行项目,然后请求接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 curl http://localhost:5000 { "todo_id" : "my_todo" , "task" : "Remeber the milk" } curl http://localhost:5000/better { "todo_id" : "my_todo" , "task" : "Remeber Me." }
那么下面我加上uri参数:
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 from flask import Flask, requestfrom flask_restful import Api, fields, marshal_with, Resourceapp = Flask(__name__) api = Api(app) resource_fields = { 'todo_id' : fields.String, 'task' : fields.String, 'uri' : fields.Url('todo' ), } class TodoDao (object ): def __init__ (self, todo_id, task ): self.todo_id = todo_id self.task = task self.status = 'active' class Todo (Resource ): @marshal_with(resource_fields ) def get (self, **kwargs ): return TodoDao(todo_id='my_todo' , task='Remeber the milk' ) class ToBeBetter (Resource ): @marshal_with(resource_fields ) def get (self, **kwargs ): return TodoDao(todo_id='my_todo' , task="Remeber Me." ) api.add_resource(Todo, '/' ) api.add_resource(ToBeBetter, '/better' ) if __name__ == '__main__' : app.run(debug=True )
然后使用curl访问接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 curl http://localhost:5000 { "todo_id" : "my_todo" , "task" : "Remeber the milk" , "uri" : "/" } curl http://localhost:5000/better { "todo_id" : "my_todo" , "task" : "Remeber Me." , "uri" : "/" }
相信这么一看大家就都明白了,那就是需要一个类来接受参数,需要一个字典来定义响应的参数,需要一个装饰器来完成根据字典的规范返回一个类。