REST,即Representational State Transfer,翻译过来叫做“表现层状态转化”。关于REST以及RESTful API的相关概念、理解等,建议参考:理解RESTful架构 - 阮一峰的网络日志。这里我们不讨论这些理论知识,而是以Flask为基础,讲解如何快速开发RESTful API。
在利用Flask开发RESTful API之前,我们需要了解标准的HTTP方法有哪些?
对应到RESTful API,得到标准的API接口:
针对上边的几种API接口的返回结果,返回状态码等,有一些规则说明:GET检索资源列表,返回一个资源数组或字典,并返回状态码200,表示请求成功。
GET检索某个特定资源,返回单个资源,并返回状态码200,表示请求成功。
POST创建新资源,返回创建后的资源,并返回状态码201,表示资源创建成功。
PUT更新资源,返回更新后的资源,并返回状态码201,表示资源更新成功。
DELETE删除资源,返回空,并返回状态码204,表示资源删除成功,服务器已无该资源。
Flask是Python中常用的一种web开发框架,关于其基本知识大家可以自行学习。这里我们利用Flask中的Flask-RESTful库,快速生成RESTful API。
首先安装Flask-RESTful库:
pip install flask-restful
我们利用官方文档Flask-RESTful documentation中的实例,讲解该扩展库的用法。由于官方实例中的一些变量名不好理解,这里稍微做一些修改。
(1)引入需要的库名、函数、变量等,并做简单的Application初始化:
from flask import Flask
from flask_restful import reqparse, abort, Api, Resource
app = Flask(__name__)
api = Api(app)
(2)定义我们需要操作的资源类型(都是json格式的):
ITEMS = {
'item1': {'name': 'Allen', 'age': 19},
'item2': {'name': 'Lily', 'age': 18},
'item3': {'name': 'James', 'age': 20},
}
(3)Flask-RESTful提供了一个用于参数解析的RequestParser类,类似于Python中自带的argparse类,可以很方便的解析请求中的-d参数,并进行类型转换。
parser = reqparse.RequestParser()
parser.add_argument('name', type=str, required=True, help='need name data')
parser.add_argument('age', type=int, required=True, help='need age data')
(4)我们观察标准的API接口,这里的接口可以分为两类:带有item_id的,和不带有item_id的。前者是操作单一资源,后者是操作资源列表或新建一个资源。
从操作单一资源开始,继承Resource类,并添加put / get / delete方法:
# 操作(put / get / delete)单一资源
class Todo(Resource):
def put(self, item_id):
args = parser.parse_args()
item = {'name': args['name'], 'age': args['age']}
ITEMS[item_id] = item
return item, 201
def get(self, item_id):
abort_if_item_doesnt_exist(item_id)
return ITEMS[item_id], 200
def delete(self, item_id):
abort_if_item_doesnt_exist(item_id)
del ITEMS[item_id]
return '', 204
(5)继续操作资源列表,继承Resource类,并添加get / post方法:
# 操作(post / get)资源列表
class TodoList(Resource):
def get(self):
return ITEMS, 200
def post(self):
args = parser.parse_args()
item_id = get_new_item_id()
ITEMS[item_id] = {'name': args['name'], 'age': args['age']}
return ITEMS[item_id], 201
(6)资源操作类定义完毕之后,需要设置路由,即告诉Python程序URL的对应关系。
# 设置路由
api.add_resource(TodoList, '/items')
api.add_resource(Todo, '/items/')
这样当我们请求url时,就能根据url类型,找到相应的资源类,并调用对应方法。
(7)使用实例:
得到资源列表:
~$ curl http://127.0.0.1:5000/items -X GET
{
"item1": {
"age": 19,
"name": "Allen"
},
"item2": {
"age": 18,
"name": "Lily"
},
"item3": {
"age": 20,
"name": "James"
}
}
得到特定资源:
~$ curl http://127.0.0.1:5000/items/item1 -X GET
{
"age": 19,
"name": "Allen"
}更新特定资源,并返回更新后的资源:
~$ curl http://127.0.0.1:5000/items/item1 -X PUT -d "name=Allen&age=20"
{
"age": 20,
"name": "Allen"
}
创建新资源,并返回创建后的资源:
~$ curl http://127.0.0.1:5000/items -X POST -d "name=Brown&age=20"
{
"age": 20,
"name": "Brown"
}
删除资源:
~$ curl http://127.0.0.1:5000/items/item4 -X DELETE
看到这里,基本的RESTful API就算是完成了,包含了数据库中数据的“增删查改”各个操作。也许很多人看完之后会觉得很简单,或者说根本就不值得自己去学习。但其实REST的基本思想虽然容易理解(这也是设计这种思想的目的),但想真正用好也不容易。本文中我们只是考虑了最最基本的用法,除此之外还有很多高级的用法和逻辑,比如:如何返回指定个数的资源,即limit操作。
如何指定资源返回时跳过的资源个数,即offset操作。
结合上边两条,如何实现分页,以及限定每页中资源的个数?
如何对返回的资源进行排序?
如何指定过滤条件?
如何实现批量操作?比如批量更新、批量删除等。
如何实现“请求验证”,即输入特定的用户名密码才会返回数据,否则认为非法请求。
如何处理各种异常?
可以想象,一个真正规范的RESTful API并不容易写,需要考虑的逻辑非常多,具体如何使用还需要大家在平时的工作中,根据自己的业务需求,自行设计。
最后老规矩,文中代码整理后Push到Github:xianhu/LearnPython
=============================================================
欢迎大家拍砖、提意见。相互交流,共同进步!
==============================================================