flask-restful使用指南
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | from flask import Flask from flask_restful import Resource, Api app = Flask(__name__) api = Api(app) class TestRestful(Resource): def get( self ): return { 'hello' : 'restful' } api.add_resource(TestRestful, '/' ) if __name__ = = '__main__' : app.run() |
演示结果
C:\Users\jh>curl http://127.0.0.1:5000/
{"hello": "restful"}
Flask-RESTful 提供的主要构建块是资源。资源构建在 Flask 可插入视图之上,
只需在资源上定义方法,就可以轻松访问多个 HTTP 方法。一个 todo 应用程序的基本 CRUD 资源是这样的:
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 from flask_restful import Resource, Api app = Flask(__name__) api = Api(app) todos = {} class TodoSimple(Resource): def get( self , todo_id): return {todo_id: todos[todo_id]} def put( 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() |
演示结果
执行
curl http://127.0.0.1:5000/todo1 -d "data=hello restful" -X put
返回 {"todo1": "hello restful"}
执行 curl http://127.0.0.1:5000/todo1
返回 {"todo1": "hello restful"}
curl http://127.0.0.1:5000/todo2 -d "data=good restful" -X put
返回 {"todo2": "good restful"}
执行 curl http://127.0.0.1:5000/todo2
返回 {"todo2": "good restful"}
Restful 能够从 view 方法中理解多种返回值。类似于 Flask,你可以返回任何可迭代的并且它将被转换成一个响应,
包括原始 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 | from flask import Flask from flask_restful import Resource, Api app = Flask(__name__) api = Api(app) class Todo1(Resource): def get( self ): return { 'msg' : 'hello restful' } class Todo2(Resource): def get( self ): return { 'msg' : 'hello restful' }, 201 class Todo3(Resource): def get( self ): return { 'msg' : 'hello restful' }, 201 , { 'new_tag' : 'this is new_tag' } api.add_resource(Todo1, '/todo1' ) api.add_resource(Todo2, '/todo2' ) api.add_resource(Todo3, '/todo3' ) if __name__ = = '__main__' : app.run() |
演示结果
C:\Users\jh>curl -i http://127.0.0.1:5000/todo1
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 25
Server: Werkzeug/2.0.1 Python/3.8.6
Date: Tue, 16 Aug 2022 10:25:25 GMT
{"msg": "hello restful"} # return 的msg
很多时候,在一个 API 中,你的资源会有多个 url。可以将多个 url 传递给 Api 对象上的 add _ resource ()方法。
每一个都将被路由到Resource
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 from flask_restful import Resource, Api app = Flask(__name__) api = Api(app) class TestRestful(Resource): def get( self ): return { 'hello' : 'restful' } class Todo(Resource): def get( self , todo_id): return { 'msg' : 'hello todo' } api.add_resource(TestRestful, '/' , '/test' ) api.add_resource(Todo, '/todo/<int:todo_id>' , endpoint = 'todo_ep' ) if __name__ = = '__main__' : app.run() |
演示结果
C:\Users\jh>curl -i http://127.0.0.1:5000/todo2
HTTP/1.0 201 CREATED # return的状态码
Content-Type: application/json
Content-Length: 25
Server: Werkzeug/2.0.1 Python/3.8.6
Date: Tue, 16 Aug 2022 10:25:27 GMT
{"msg": "hello restful"} # return 的msg
C:\Users\jh>curl -i http://127.0.0.1:5000/todo3
HTTP/1.0 201 CREATED # return的状态码
Content-Type: application/json
Content-Length: 25
new_tag: this is new_tag #return 的new_tag
Server: Werkzeug/2.0.1 Python/3.8.6
Date: Tue, 16 Aug 2022 10:25:32 GMT
{"msg": "hello restful"} # return 的msg
C:\Users\jh>curl -i http://127.0.0.1:5000/
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 21
Server: Werkzeug/2.0.1 Python/3.8.6
Date: Tue, 16 Aug 2022 10:58:32 GMT
{"hello": "restful"}
C:\Users\jh>curl -i http://127.0.0.1:5000/test
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 21
Server: Werkzeug/2.0.1 Python/3.8.6
Date: Tue, 16 Aug 2022 10:58:42 GMT
{"hello": "restful"}
C:\Users\jh>curl -i http://127.0.0.1:5000/todo/1
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 22
Server: Werkzeug/2.0.1 Python/3.8.6
Date: Tue, 16 Aug 2022 10:59:02 GMT
{"msg": "hello todo"}
C:\Users\jh>curl -i http://127.0.0.1:5000/todo/2
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 22
Server: Werkzeug/2.0.1 Python/3.8.6
Date: Tue, 16 Aug 2022 10:59:06 GMT
{"msg": "hello todo"}
虽然 Flask 可以方便地访问请求数据(即 querystring 或 POST 表单编码的数据) ,
但验证表单数据仍然是一件痛苦的事情。使用类似于 argparse 的库对请求数据验证提供内置支持。
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 | from flask import Flask from flask_restful import reqparse, Resource, Api app = Flask(__name__) api = Api(app) parser = reqparse.RequestParser() parser.add_argument( 'rate' , type = int , help = 'rate to change for this resource' ) class Todo(Resource): def post( self ): args = parser.parse_args() print ( 'args: %s' % args) return { 'msg' : 'hello333 restful' } def get( self ): args = parser.parse_args() print ( 'args: %s' % args) return { 'msg' : 'hello444 restful' } api.add_resource(Todo, '/todos' ) if __name__ = = '__main__' : app.run(debug = True ) |
演示结果
使用curl时,-d 后面的参数需要用双引号,否则可能获取不到参数
C:\Users\jh>curl -H "charset=utf-8" -d 'rate=110' http://127.0.0.1:5000/todos
{
"msg": "hello333 restful"
}
C:\Users\jh>curl -d "rate=123" http://127.0.0.1:5000/todos
{
"msg": "hello333 restful"
}
C:\Users\jh>curl -d "rate=123s" http://127.0.0.1:5000/todos
{
"message": {
"rate": "rate to change for this resource"
}
}
C:\Users\jh>curl http://127.0.0.1:5000/todos?rate=234
{
"msg": "hello444 restful"
}
C:\Users\jh>curl http://127.0.0.1:5000/todos?rate2=234
{
"msg": "hello444 restful"
}
服务端日志
127.0.0.1 - - [18/Aug/2022 11:04:44] "POST /todos HTTP/1.1" 200 -
args: {'rate': None}
127.0.0.1 - - [18/Aug/2022 11:04:51] "POST /todos HTTP/1.1" 200 -
args: {'rate': None}
127.0.0.1 - - [18/Aug/2022 11:04:54] "POST /todos HTTP/1.1" 200 -
args: {'rate': 123}
127.0.0.1 - - [18/Aug/2022 11:05:30] "POST /todos HTTP/1.1" 400 -
args: {'rate': 234}
127.0.0.1 - - [18/Aug/2022 11:06:08] "GET /todos?rate=234 HTTP/1.1" 200 -
127.0.0.1 - - [18/Aug/2022 11:06:12] "GET /todos?rate2=234 HTTP/1.1" 200 -
args: {'rate': None}
默认情况下,在你的返回迭代中所有字段将会原样呈现。尽管当你刚刚处理 Python 数据结构的时候,觉得这是一个伟大的工作,
但是当实际处理它们的时候,会觉得十分沮丧和枯燥。为了解决这个问题,Flask-RESTful 提供了 fields 模块和 marshal_with() 装饰器。
类似 Django ORM 和 WTForm,你可以使用 fields 模块来在你的响应中格式化结构。
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 | from flask import Flask from flask_restful import Resource, Api, fields, marshal_with app = Flask(__name__) api = Api(app) resource_fields = { '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 = 'watch the car' ) api.add_resource(Todo, '/todo' ) if __name__ = = '__main__' : app.run(debug = True ) |
C:\Users\jh>curl http://127.0.0.1:5000/todo
{
"task": "watch the car",
"uri": "/todo"
}
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 | from flask import Flask from flask_restful import Resource, Api, reqparse, abort app = Flask(__name__) api = Api(app) TODOS = { 'todo1' : { 'task' : 'build an api' }, 'todo2' : { 'task' : '??????' }, 'todo3' : { 'task' : 'profit!' }, } def abort_if_todo_doesnt_exist(todo_id): if todo_id not in TODOS: abort( 404 , message = "Todo {} doesn't exist" . format (todo_id)) parser = reqparse.RequestParser() parser.add_argument( 'task' ) class Todo(Resource): def get( self , todo_id): abort_if_todo_doesnt_exist(todo_id) return TODOS[todo_id] def delete( self , todo_id): abort_if_todo_doesnt_exist(todo_id) del TODOS[todo_id] return '', 204 def put( self , todo_id): args = parser.parse_args() task = { 'task' : args[ 'task' ]} TODOS[todo_id] = task return task, 201 class TodoList(Resource): def get( self , * * kwargs): return TODOS def post( self ): args = parser.parse_args() todo_id = int ( max (TODOS.keys()).lstrip( 'todo' )) + 1 todo_id = 'todo%i' % todo_id TODOS[todo_id] = { 'task' : args[ 'task' ]} return TODOS[todo_id], 201 api.add_resource(TodoList, '/todos' ) api.add_resource(Todo, '/todos/<todo_id>' ) if __name__ = = '__main__' : app.run(debug = True ) |
演示结果
C:\Users\jh>curl http://127.0.0.1:5000/todos
{
"todo1": {
"task": "build an api"
},
"todo2": {
"task": "??????"
},
"todo3": {
"task": "profit!"
}
}
C:\Users\jh>curl http://127.0.0.1:5000/todos/todo3
{
"task": "profit!"
}
C:\Users\jh>curl http://127.0.0.1:5000/todos/todo4
{
"message": "Todo todo4 doesn't exist"
}
C:\Users\jh>curl http://localhost:5000/todos/todo2 -X DELETE -v
* Trying 127.0.0.1:5000...
* Connected to localhost (127.0.0.1) port 5000 (#0)
> DELETE /todos/todo2 HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.83.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
* HTTP 1.0, assume close after body
< HTTP/1.0 204 NO CONTENT
< Content-Type: application/json
< Server: Werkzeug/2.0.1 Python/3.8.6
< Date: Thu, 18 Aug 2022 06:10:09 GMT
<
* Closing connection 0
C:\Users\jh>curl http://127.0.0.1:5000/todos/todo2
{
"message": "Todo todo2 doesn't exist"
}
C:\Users\jh>curl http://localhost:5000/todos -d "task=something new" -X POST -v
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 127.0.0.1:5000...
* Connected to localhost (127.0.0.1) port 5000 (#0)
> POST /todos HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.83.1
> Accept: */*
> Content-Length: 18
> Content-Type: application/x-www-form-urlencoded
>
* Mark bundle as not supporting multiuse
* HTTP 1.0, assume close after body
< HTTP/1.0 201 CREATED
< Content-Type: application/json
< Content-Length: 32
< Server: Werkzeug/2.0.1 Python/3.8.6
< Date: Thu, 18 Aug 2022 06:10:53 GMT
<
{
"task": "something new"
}
* Closing connection 0
C:\Users\jh>curl http://127.0.0.1:5000/todos/todo4
{
"task": "something new"
}
C:\Users\jh>curl http://localhost:5000/todos/todo3 -d "task=something different" -X PUT -v
* Trying 127.0.0.1:5000...
* Connected to localhost (127.0.0.1) port 5000 (#0)
> PUT /todos/todo3 HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.83.1
> Accept: */*
> Content-Length: 24
> Content-Type: application/x-www-form-urlencoded
>
* Mark bundle as not supporting multiuse
* HTTP 1.0, assume close after body
< HTTP/1.0 201 CREATED
< Content-Type: application/json
< Content-Length: 38
< Server: Werkzeug/2.0.1 Python/3.8.6
< Date: Thu, 18 Aug 2022 06:15:31 GMT
<
{
"task": "something different"
}
* Closing connection 0
C:\Users\jh>curl http://127.0.0.1:5000/todos/todo3
{
"task": "something different"
}
C:\Users\jh>curl http://127.0.0.1:5000/todos
{
"todo1": {
"task": "build an api"
},
"todo3": {
"task": "something different"
},
"todo4": {
"task": "something new"
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了