Flask学习笔记(1)创建RESTful API

  从本文起,笔者将会更新一系列Flask学习笔记。
  本文将会讲述在Flask中如何创建RESTful API。在此之前,我们有必要了解下什么是RESTful架构。

RESTful架构

  RESTful架构自从2000年被Roy Feilding提出后就受到广泛关注,并被成功地应用于成千上万的系统之中。REST已经是web相关应用中的重要技术之一,它极有可能也会在手机和IOT相关应用中快速增长。RESTful架构受欢迎之处,在于它是目前最流行的一种互联网软件架构,其结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。
  那么,什么是RESTful架构?
  REST,即Representational State Transfer的缩写。

RESTful架构示意图

资源(Resources)

  REST的名称"表现层状态转化"中,省略了主语。“表现层"其实指的是"资源”(Resources)的"表现层"。
  所谓"资源",就是网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的实在。你可以用一个URI(统一资源定位符)指向它,每种资源对应一个特定的URI。要获取这个资源,访问它的URI就可以,因此URI就成了每一个资源的地址或独一无二的识别符。

表现层(Representation)

  “资源"是一种信息实体,它可以有多种外在表现形式。我们把"资源"具体呈现出来的形式,叫做它的"表现层”(Representation)。
  比如,文本可以用txt格式表现,也可以用HTML格式、XML格式、JSON格式表现,甚至可以采用二进制格式;图片可以用JPG格式表现,也可以用PNG格式表现。
  URI只代表资源的实体,不代表它的形式。它的具体表现形式,应该在HTTP请求的头信息中用Accept和Content-Type字段指定,这两个字段才是对"表现层"的描述。

状态转化(State Transfer)

  访问一个网站,就代表了客户端和服务器的一个互动过程。在这个过程中,势必涉及到数据和状态的变化。
  互联网通信协议HTTP协议,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(State Transfer)。而这种转化是建立在表现层之上的,所以就是"表现层状态转化"。
  客户端用到的手段,只能是HTTP协议。具体来说,就是HTTP协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源。

动词 CRUD URL 操作
GET Read http://host/resource 获取所有的资源
GET Read http://host/resource/1 获取id为1的资源
POST Create http://host/resource 使用POST方法,从表格(form)数据中新建资源
PUT Update http://host/resource/1 对id为1的现有资源进行修改
DELETE Delete http://host/resource/1 删除id为1的资源

关于RESTful API的例子

  下面我们将用Flask框架来实现RESTful风格的API,用于模拟数据库中persons表中的新增、修改、查询和删除操作。
  完整的Python实现代码如下:

# -*- coding: utf-8 -*-
from flask import Flask, request, jsonify


app = Flask(__name__)

persons = [{
    
    'name': 'Alex', 'city': 'New York'},
           {
    
    'name': 'Bob', 'city': 'London'}]


@app.route('/persons', methods=['GET'])
def index():
    return jsonify(persons)


@app.route('/persons/<int:_id>', methods=['GET'])
def get_person_by_id(_id):
    if _id in range(len(persons)):
        return jsonify(persons[_id])
    else:
        return jsonify(f"{
      
      _id} is not in db.")


@app.route('/persons/<int:_id>', methods=['PUT'])
def update_person_by_id(_id):
    data = request.json
    if data['city']:
        persons[_id]["city"] = data['city']
    if data['name']:
        persons[_id]["name"] = data['name']
    return jsonify({
    
    "person": data})


@app.route('/persons/<int:_id>', methods=['DELETE'])
def delete_person_by_id(_id):
    if _id in range(len(persons)):
        person = persons[_id]
        persons.remove(person)
        return jsonify(person)
    else:
        return jsonify(f"{
      
      _id} is not in db.")


@app.route('/persons', methods=['POST'])
def create_person():
    data = request.json
    persons.append(data)
    return jsonify({
    
    "person": data})


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000, debug=True)

  已有Python第三方模块flask-restful可快速完成Restful风格的API开发,实现代码如下:

# -*- coding: utf-8 -*-
from flask import Flask
from flask_restful import reqparse, abort, Api, Resource

app = Flask(__name__)
api = Api(app)

persons = [{
    
    'name': 'Tom', 'city': 'New York'},
           {
    
    'name': 'Green', 'city': 'London'}]


def abort_person_doesnt_exist(_id):
    if _id not in range(len(persons)):
        abort(404, message=f"id {
      
      _id} doesn't exist")


parser = reqparse.RequestParser()
parser.add_argument('name', type=str, default='')
parser.add_argument('city', type=str, default='')


class Person(Resource):
    def get(self, _id):
        abort_person_doesnt_exist(_id)
        return persons[_id]

    def delete(self, _id):
        abort_person_doesnt_exist(_id)
        person = persons[_id]
        persons.remove(person)
        return person

    def put(self, _id):
        abort_person_doesnt_exist(_id)
        args = parser.parse_args()
        if args['city']:
            persons[_id]["city"] = args['city']
        if args['name']:
            persons[_id]["name"] = args['name']
        return persons[_id]


class Persons(Resource):
    def get(self):
        return persons

    def post(self):
        args = parser.parse_args()
        persons.append({
    
    'name': args['name'], 'city': args['city']})
        return args


api.add_resource(Persons, '/persons')
api.add_resource(Person, '/persons/<int:_id>')


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000, debug=True)

利用Postman发送请求

  我们使用Postman来发送HTTP请求,用于测试接口是否完成对应的功能。以下是测试过程

  • 获取所有的人物(GET请求)
    获取所有的人物
  • 获取id为1的人物(GET请求)
    获取id为1的人物
  • 获取id为2的人物(GET请求,会报错)
    获取id为2的人物
  • 修改id为1的人物(PUT请求)
    修改id为1的人物
  • 获取所有的人物(GET请求)
    获取所有的人物
  • 新增人物(POST请求)
    新增人物
  • 获取所有的人物(GET请求,此时获取id为2的人物不会报错)
    获取所有的人物
  • 删除id为1的人物(DELETE请求)
    删除id为1的人物
  • 获取所有的人物(GET请求)
    获取所有的人物

总结

  本文重点介绍了Restful框架,以及如何在Flask中实现Restful风格的API。
  Flask是一个简单好用,稳定高效,且久经考验的Web框架,笔者后续将持续地学习Flask框架并输出文章及自己的体会和心得,欢迎大家关注。

参考文献

  1. 书籍Mastering Flask Web Development(Second Edition), Daniel Gasper and Jack Stouffer, Chapter 8, Page 157-166
  2. Flask-RESTful: http://www.pythondoc.com/Flask-RESTful/index.html

猜你喜欢

转载自blog.csdn.net/jclian91/article/details/108502990