9-----基于flask_restful模块构建一个优雅的后端服务器

首先安装模块:
pip install flask-restful

##官方文档的例子:
from flask import Flask
from flask_restful import Resource,Api

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

class HelloWorld(Resource):
    def get(self):
        return {'hello': 'world'}

api.add_resource(HelloWorld, '/')

if __name__ == '__main__':
    app.run(debug=True)

####测试访问get请求:
[root@localhost opt]# curl http://127.0.0.1:5000/
{
    "hello": "world"
}

2、添加路由:
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(debug=True)

###测试访问请求:
[root@localhost opt]# curl http://127.0.0.1:5000/todo1 -d 'data=apple' -X PUT
{
    "todo1": "apple"
}
[root@localhost opt]# curl http://127.0.0.1:5000/todo1
{
    "todo1": "apple"
}

由于是form['data']所以我们传的参数一定是data:
[root@localhost opt]# curl http://127.0.0.1:5000/todo1 -d 'task=jimi' -X PUT
{
    "message": "The browser (or proxy) sent a request that this server could not understand."
}

3、多个类型返回值:
[root@localhost opt]# cat test_rest.py 
from flask import Flask, request
from flask_restful import Resource, Api

app = Flask(__name__)
api = Api(app)
todos = {}

class Todo1(Resource):
    def get(self):
        return {'task': 'apple'}

class Todo2(Resource):
    def get(self):
        return {'task': 'babana'}, 201

class Todo3(Resource):
    def get(self):
        return {'task': 'Hello world'}, 201, {'Etag': 'some-opaque-string'}

api.add_resource(Todo1, '/Todo1')
api.add_resource(Todo2, '/Todo2')
api.add_resource(Todo3, '/Todo3')


if __name__ == "__main__":
    app.run(debug=True)

##测试:
[root@localhost opt]# curl -i http://127.0.0.1:5000/Todo1
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 24
Server: Werkzeug/0.15.6 Python/3.6.4
Date: Tue, 15 Oct 2019 16:41:09 GMT

{
    "task": "apple"
}

#头部信息:
[root@localhost opt]# curl -i http://127.0.0.1:5000/Todo3
HTTP/1.0 201 CREATED
Content-Type: application/json
Content-Length: 30
Etag: some-opaque-string
Server: Werkzeug/0.15.6 Python/3.6.4
Date: Tue, 15 Oct 2019 16:41:31 GMT

{
    "task": "Hello world"
}

4、多个URL访问同一个源:

from flask import Flask
from flask_restful import Resource, Api

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

class HelloWorld(Resource):
    def get(self):
        return {'hello': 'world'}

api.add_resource(HelloWorld, '/', '/hello')

if __name__ == '__main__':
    app.run(debug=True)

##测试:

[root@localhost opt]# curl http://127.0.0.1:5000/
{
    "hello": "world"
}
[root@localhost opt]# curl http://127.0.0.1:5000/hello
{
    "hello": "world"
}

5、上一讲的为例,改造这个模块:
[root@localhost opt]# cat test_rest.py 
from flask import Flask,abort, make_response, request
from flask_restful import Resource, Api

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

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
    }
]

class TaskListAPI(Resource):
    def get(self):
        return jsonify({'tasks': tasks})

    def post(self):
        if not request.json or not 'title' in request.json:
            abort(400)
            task = {
               'id': tasks[-1]['id'] + 1,
               'title': request.json['title'],
               'description': request.json.get('description', ""),
               'done': False
            }
            tasks.append(task)
            return jsonify({'task': task}), 201


class TaskAPI(Resource):
    def get(self, id):
        if id:
            task = [i for i in tasks if i['id']==id] 
            if len(task) == 0:
                abort(404)
            return jsonify({'task': task})

    def put(self, id):
        task = [i for i in tasks if i['id']==id]
        if len(task) == 0:
            abort(404)
        if not request.json:
            abort(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)
        if 'done' in request.json and type(request.json['done']) is not bool:
            abort(400)
        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})


    def delete(self, id):
        task = [i for i in tasks if i['id']==id]
        if len(task) == 0:
            abort(404)
        tasks.remove(task[0]) 
        return jsonify({'result': True})

api.add_resource(TaskListAPI, '/devops/api/v1.0/tasks', endpoint = 'tasks')
api.add_resource(TaskAPI, '/devops/api/v1.0/tasks/<int:id>', endpoint = 'task')

if __name__ == '__main__':
    app.run(debug=True)

##测试:

[root@localhost opt]# curl -i -X GET http://localhost:5000/devops/api/v1.0/tasks/1
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 162
Server: Werkzeug/0.15.6 Python/3.6.4
Date: Wed, 16 Oct 2019 02:03:38 GMT

{
  "task": [
    {
      "description": "Milk, Cheese, Pizza, Fruit, Tylenol", 
      "done": false, 
      "id": 1, 
      "title": "Buy groceries"
    }
  ]
}
[root@localhost opt]# curl -i -X GET http://localhost:5000/devops/api/v1.0/tasks
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 317
Server: Werkzeug/0.15.6 Python/3.6.4
Date: Wed, 16 Oct 2019 02:03:40 GMT

{
  "tasks": [
    {
      "description": "Milk, Cheese, Pizza, Fruit, Tylenol", 
      "done": false, 
      "id": 1, 
      "title": "Buy groceries"
    }, 
    {
      "description": "Need to find a good Python tutorial on the web", 
      "done": false, 
      "id": 2, 
      "title": "Learn Python"
    }
  ]
}
###POST:
[root@localhost opt]#  curl -i -H "Content-Type: application/json" -X POST -d '{"title":"Read a book"}' http://localhost:5000/devops/api/v1.0/tasks
HTTP/1.0 201 CREATED
Content-Type: application/json
Content-Length: 105
Server: Werkzeug/0.15.6 Python/3.6.4
Date: Wed, 16 Oct 2019 02:04:23 GMT

{
  "task": {
    "description": "", 
    "done": false, 
    "id": 3, 
    "title": "Read a book"
  }
}
[root@localhost opt]# curl -i -X GET http://localhost:5000/devops/api/v1.0/tasks
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 424
Server: Werkzeug/0.15.6 Python/3.6.4
Date: Wed, 16 Oct 2019 02:04:29 GMT

{
  "tasks": [
    {
      "description": "Milk, Cheese, Pizza, Fruit, Tylenol", 
      "done": false, 
      "id": 1, 
      "title": "Buy groceries"
    }, 
    {
      "description": "Need to find a good Python tutorial on the web", 
      "done": false, 
      "id": 2, 
      "title": "Learn Python"
    }, 
    {
      "description": "", 
      "done": false, 
      "id": 3, 
      "title": "Read a book"
    }
  ]
}

##PUT和DELETE:
[root@localhost opt]# curl -i -H "Content-Type: application/json" -X PUT -d '{"done":true}' http://localhost:5000/devops/api/v1.0/tasks/2
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 171
Server: Werkzeug/0.15.6 Python/3.6.4
Date: Wed, 16 Oct 2019 02:05:23 GMT

{
  "task": [
    {
      "description": "Need to find a good Python tutorial on the web", 
      "done": true, 
      "id": 2, 
      "title": "Learn Python"
    }
  ]
}


##DELETE:

[root@localhost opt]# curl -i -X DELETE http://localhost:5000/devops/api/v1.0/tasks/3
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 21
Server: Werkzeug/0.15.6 Python/3.6.4
Date: Wed, 16 Oct 2019 02:06:25 GMT

{
  "result": true
}
[root@localhost opt]# curl -i -X GET http://localhost:5000/devops/api/v1.0/tasks
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 316
Server: Werkzeug/0.15.6 Python/3.6.4
Date: Wed, 16 Oct 2019 02:06:27 GMT

{
  "tasks": [
    {
      "description": "Milk, Cheese, Pizza, Fruit, Tylenol", 
      "done": false, 
      "id": 1, 
      "title": "Buy groceries"
    }, 
    {
      "description": "Need to find a good Python tutorial on the web", 
      "done": true, 
      "id": 2, 
      "title": "Learn Python"
    }
  ]
}


###但是我们发现在POST和PUT定义参数的时候又臭又长,这个时候,我们需要一个检查机制,Flask-RESTful 提供了一个更好的方式来处理数据验证,它叫做 RequestParser 类。这个类工作方式类似命令行解析工具 argparse。

class TaskListAPI(Resource):
    def __init__(self):
        self.reqparse = reqparse.RequestParser()
        self.reqparse.add_argument('title', type = str, required = True,
            help = 'No task title provided', location = 'json')
        self.reqparse.add_argument('description', type = str, default = "", location = 'json')
        super(TaskListAPI, self).__init__()

 def __init__(self):
        self.reqparse = reqparse.RequestParser()
        self.reqparse.add_argument('title', type = str, location = 'json')
        self.reqparse.add_argument('description', type = str, location = 'json')
        self.reqparse.add_argument('done', type = bool, location = 'json')
        super(TaskAPI, self).__init__()


###PUT请求直接解析数据:
    def put(self, id):
        task = [i for i in tasks if i['id']==task_id]
        if len(task) == 0:
            abort(404)
        task=task[0]
        args = self.reqparse.parse_args()
        for k, v in args.iteritems():
            if v != None:
                task[k] = v
        return jsonify({'task': task})

##验证:
[root@localhost ~]# curl -i -H "Content-Type: application/json" -X POST -d '{"test":"Read a book"}' http://localhost:5000/devops/api/v1.0/tasks
HTTP/1.0 400 BAD REQUEST
Content-Type: application/json
Content-Length: 69
Server: Werkzeug/0.15.6 Python/3.6.4
Date: Wed, 16 Oct 2019 14:02:48 GMT

{
    "message": {
        "title": "No task title provided"
    }
}


##POST请求修改:
    def post(self):
        args = self.reqparse.parse_args()
        task = {
            'id': tasks[-1]['id'] + 1,
             'title': args.get('title',''),
             'description': args.get('description', ""),
             'done': False
          }
        tasks.append(task)
        return jsonify({'tasks':tasks})

#########总体文件:

[root@localhost opt]# cat test_rest.py 
from flask import Flask,abort, make_response, request,jsonify
from flask_restful import Resource, Api, reqparse

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

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
    }
]

class TaskListAPI(Resource):
    def __init__(self):
        self.reqparse = reqparse.RequestParser()
        self.reqparse.add_argument('title', type = str, required = True,help = 'No task title provided', location = 'json')
        self.reqparse.add_argument('description', type = str, default = "", location = 'json')
        super(TaskListAPI, self).__init__()

    def get(self):
        return jsonify({'tasks': tasks})

    def post(self):
        args = self.reqparse.parse_args()
        task = {
            'id': tasks[-1]['id'] + 1,
             'title': args.get('title',''),
             'description': args.get('description', ""),
             'done': False
          }
        tasks.append(task)
        return jsonify({'tasks':tasks})


class TaskAPI(Resource):
    def __init__(self):
        self.reqparse = reqparse.RequestParser()
        self.reqparse.add_argument('title', type = str, location = 'json')
        self.reqparse.add_argument('description', type = str, location = 'json')
        self.reqparse.add_argument('done', type = bool, location = 'json')
        super(TaskAPI, self).__init__()

    def get(self, id):
        if id:
            task = [i for i in tasks if i['id']==id] 
            if len(task) == 0:
                abort(404)
            return jsonify({'task': task})

    def put(self, id):
        task = [i for i in tasks if i['id']==id]
        if len(task) == 0:
            abort(404)
        task=task[0]
        args = self.reqparse.parse_args()
        for k, v in args.items():
            if v != None:
                task[k] = v
        return jsonify({'task': task})


    def delete(self, id):
        task = [i for i in tasks if i['id']==id]
        if len(task) == 0:
            abort(404)
        tasks.remove(task[0]) 
        return jsonify({'result': True})

api.add_resource(TaskListAPI, '/devops/api/v1.0/tasks', endpoint = 'tasks')
api.add_resource(TaskAPI, '/devops/api/v1.0/tasks/<int:id>', endpoint = 'task')



if __name__ == '__main__':
    app.run(debug=True)

 

posted @ 2020-04-06 21:06  王竹笙  阅读(459)  评论(0编辑  收藏  举报