[Flask] 03 - Restful API vs GraphQL
Ref: Use Postman to call a REST API
测试 REST API.
GraphQL
/* implement */
Restful API
一、Flask的本质
Ref: 用flask写Restful API
Flask呢,仅仅只是实现了web框架最核心的功能(实际就是一个socket服务器, 用户的浏览器就是一个socket客户端),有大量的第三方组件,比如ORM框架既可以选flask-sqlalchemy,也可以选flask-mongoengine,可扩展可定制,这是Flask最大的优点了, 通过这些第三方组件的组合,其实Flask也差不多是Django了。
二、Flask来写一个Restful API
Flask原生就对Restful的支持已经做的很好了,JSON目前是Restful API的主流数据传输方式,Flask可以通过jsonify()将python的dict或list转成JSON。
from flask import Flask, request, jsonify app = Flask(__name__) # 假设这是数据库存储的数据 USER_LIST = [{'id': 1, 'name': 'zws', 'age': 18}, {'id': 2, 'name': 'Tom', 'age': 19}] @app.route('/user', methods=['GET']) def get(): # GET请求获取全部的数据 return jsonify({'code': 200, 'msg': 'ok', 'data': USER_LIST}) if __name__ == '__main__': app.run(debug=True)
RESTful架构的特点:
- 每一个URI代表一种资源;
- 客户端和服务器之间,传递这种资源的某种表现层;把"资源"具体呈现出来的形式,叫做它的"表现层"(Representation)。比如,文本可以用txt格式表现,也可以用HTML格式、XML格式、JSON格式表现,甚至可以采用二进制格式;图片可以用JPG格式表现,也可以用PNG格式表现。
- 客户端通过四个HTTP动词,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源。
使用Python Flask 实现Restful API
第一步,规划一个根URL,例如:
http://[hostname]/todo/api/v1.0/
第二步,规划资源的URL,这个例子十分简单,只有任务清单。
【GET】
#!flask/bin/python from flask import Flask, jsonify app = Flask(__name__) tasks = [ { 'id': 1, 'title': u'Buy groceries', 'description': u'Milk, Cheese, Pizza, Fruit, Tylenol', 'done': False }, { 'id': 2, 'title': u'Learn Python', 'description': u'Need to find a good Python tutorial on the web', 'done': False } ] @app.route('/todo/api/v1.0/tasks', methods=['GET']) def get_tasks(): return jsonify({'tasks': tasks}) if __name__ == '__main__': app.run(debug=True)
浏览器端获得 (GET) 的内容。
如果只获得其中的一条,进行判断。
from flask import abort @app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['GET']) def get_task(task_id): # 检查tasks内部的元素,是否有元素的id值和参数相匹配 task = list(filter(lambda t: t['id'] == task_id, tasks)) # 有的话,就返回列表形式包裹的这个元素,没有的话就报错404 if len(task) == 0: abort(404)
return jsonify({'task': task[0]}) # 否则,将这个task以json的格式返回。
【POST】
从 request.json 中获得 浏览器发来的内容。
from flask import request @app.route('/todo/api/v1.0/tasks', methods=['POST']) def create_task(): # 如果请求里面没有json数据,或者json数据里面title的内容为空 if not request.json or not 'title' in request.json: abort(400) # 返回404错误
task = { 'id': tasks[-1]['id'] + 1, # 取末尾tasks的id号+1 'title': request.json['title'], # title 必须设置,不能为空。 'description': request.json.get('description', ""), 'done': False } tasks.append(task) # 完了之后,添加这个task进tasks列表
return jsonify({'task': task}), 201 # 并且返回这个添加的task内容和状态码。
【PUT】
更新内容。
@app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['PUT']) def update_task(task_id): #检查是否有这个id数据 task = filter(lambda t: t['id'] == task_id, tasks) if len(task) == 0: abort(404)
#如果请求中没有附带json数据,则报错400 if not request.json: abort(400)
#如果title对应的值,不是字符串类型,则报错400 if 'title' in request.json and type(request.json['title']) != unicode: abort(400)
if 'description' in request.json and type(request.json['description']) is not unicode: abort(400)
#检查done对应的值是否是布尔值 if 'done' in request.json and type(request.json['done']) is not bool: abort(400)
#如果上述条件全部通过的话,更新title的值,同时设置默认值 task[0]['title'] = request.json.get('title', task[0]['title']) task[0]['description'] = request.json.get('description', task[0]['description']) task[0]['done'] = request.json.get('done', task[0]['done'])
#返回修改后的数据 return jsonify({'task': task[0]})
【DELETE】
删除某一项。
@app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['DELETE']) def delete_task(task_id): # 检查是否有这个数据 task = filter(lambda t: t['id'] == task_id, tasks) if len(task) == 0: abort(404)
# 从tasks列表中删除这个值 tasks.remove(task[0])
# 返回结果状态,自定义的result return jsonify({'result': True})
End.