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 來源:簡書 簡書著作權歸作者所有,任何形式的轉載都請聯繫作者獲得授權並註明出處。

Exit mobile version