Python的Flask框架开发RESTful API
- 2019 年 10 月 6 日
- 筆記
web框架选择
- Django,流行但是笨重,还麻烦,人生苦短,肯定不选
- web.py,轻量,但据说作者仙逝无人维护,好吧,先pass
- tornado,据说倡导自己造轮子,虽然是facebook开源的吧,但听到这个,就算了吧
- flask,轻量,流行,可以自己定义
安装flask
pip install flask
flask前端模板引擎默认是jinja2,所以我们还需要安装jinja2
pip install jinja2
hello world
from flask import Flask from flask import request app = Flask(__name__) @app.route('/', methods=['GET', 'POST']) def home(): return '<h1>hello world</h1>' if __name__ == '__main__': app.run()
运行python app.py,Flask自带的Server在端口5000上监听:
打开浏览器,输入首页地址http://localhost:5000/:
会出现hello world
简单的RESTful实现
#!/usr/bin/env python # -*- coding: utf-8 -*- # by vellhe 2017/7/9 from flask import Flask, abort, request, jsonify app = Flask(__name__) # 测试数据暂时存放 tasks = [] @app.route('/add_task/', methods=['POST']) def add_task(): if not request.json or 'id' not in request.json or 'info' not in request.json: abort(400) task = { 'id': request.json['id'], 'info': request.json['info'] } tasks.append(task) return jsonify({'result': 'success'}) @app.route('/get_task/', methods=['GET']) def get_task(): if not request.args or 'id' not in request.args: # 没有指定id则返回全部 return jsonify(tasks) else: task_id = request.args['id'] task = filter(lambda t: t['id'] == int(task_id), tasks) return jsonify(task) if task else jsonify({'result': 'not found'}) if __name__ == "__main__": # 将host设置为0.0.0.0,则外网用户也可以访问到这个服务 app.run(host="0.0.0.0", port=8383, debug=True)
验证结果

image.png

image.png

image.png
以上是通过最原始的方式实现,没有使用flask的RESTful扩展库
使用flask的RESTful扩展库 flask-restful
安装Flask-RESTful库:
pip install flask-restful
demo
#!/usr/bin/env python # -*- coding: utf-8 -*- # by vellhe 2017/7/9 from flask import Flask from flask_restful import reqparse, abort, Api, Resource 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') # # 操作(put / get / delete)单一资源Todo # shows a single todo item and lets you delete a todo item 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 # # 操作(post / get)资源列表TodoList # shows a list of all todos, and lets you POST to add new tasks class TodoList(Resource): def get(self): 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)
(1)引入需要的库名、函数、变量等,并做简单的Application初始化:
from flask import Flask from flask_restful import reqparse, abort, Api, Resource app = Flask(__name__) api = Api(app)
(2)定义我们需要操作的资源类型(都是json格式的):
TODOS = { 'todo1': {'task': 'build an API'}, 'todo2': {'task': '哈哈哈'}, 'todo3': {'task': 'profit!'}, }
(3)Flask-RESTful提供了一个用于参数解析的RequestParser类,类似于Python中自带的argparse类,可以很方便的解析请求中的-d参数,并进行类型转换。
parser = reqparse.RequestParser() parser.add_argument('task')
(4)我们观察标准的API接口,这里的接口可以分为两类:带有item_id的,和不带有item_id的。前者是操作单一资源,后者是操作资源列表或新建一个资源。
从操作单一资源开始,继承Resource类,并添加put / get / delete方法:
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
(5)继续操作资源列表,继承Resource类,并添加get / post方法:
class TodoList(Resource): def get(self): 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
(6)资源操作类定义完毕之后,需要设置路由,即告诉Python程序URL的对应关系。
api.add_resource(TodoList, '/todos') api.add_resource(Todo, '/todos/<todo_id>')
这样当我们请求url时,就能根据url类型,找到相应的资源类,并调用对应方法。
验证结果
查询列表:

image.png
查询单任务:

image.png
删除任务:

image.png
添加任务(这是用post表单形式,还可以改成json形式啦):

image.png
更新任务:

作者:我为峰2014 链接:https://www.jianshu.com/p/ed1f819a7b58 来源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。