1. 程式人生 > >筆記︱利用python + flask製作一個簡易本地restful API

筆記︱利用python + flask製作一個簡易本地restful API

pip install flask-restful

.

一、案例解析

由一個完整案例解析:

from flask import Flask
from flask.ext.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', type=str) # Todo # show a single todo item and lets you delete them 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 # 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 ## ## Actually setup the Api resource routing here ## api.add_resource(TodoList, '/todos') api.add_resource(Todo, '/todos/<todo_id>') if __name__ == '__main__': app.run(debug=True)

1、rescouce資源部分

1.1 TODOS ,任務列表

相當於資料庫,如果是大型API呼叫,後臺需要資料庫支援才行,其中的todo1是子項任務;

1.2 api = Api(app)

Flask-RESTful 提供的最主要的基礎就是資源(resources),可以通過.add_resource新增資源resource,

    api.add_resource(TodoList, '/todos')
    api.add_resource(Todo, '/todos/<todo_id>')

把內容TodoList列表,賦值給/todos,把Todo子項賦值給’/todos/’
該操作可以讓子項分離之後用requests 來呼叫。

1.3 新加任務:post

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

有新加的任務,todo的編號+1,同時儲存到TODOS

1.4 class Todo(Resource):

設定todo任務,使其可以用其他內容調取子項任務,這裡有get(得到任務)/delete(刪除任務)/put(更新任務)
與TodoList是平行資源,分管一個連結欄位,’/todos/’

1.5 class TodoList(Resource):

專案列表,get(得到任務)/post(上傳任務),分管’/todos’

1.6 判斷欄位是否存在

可以作為安全組進行密碼驗證.

def api_key_audit(api_keys):
     if api_key not in api_keys:
         abort(404, message="api key {} doesn't exist".format(api_key))

1.7 debug選項的開啟

debug的作用是,如果你修改了app.py檔案,並且儲存之後,就會立即重新載入一遍app.py

一般來說,正式環境下不能開啟,不然改了一下檔案,就會重啟

1.8 app.run()函式

run(self, host=None, port=None, debug=None, **options)

預設的host = 5000,port = 127.0.0.1

2、網頁內容

abort_if_todo_doesnt_exist函式,報錯機制,如果沒有該任務號,則會顯示404錯誤;
引數解析reqparse:
驗證表單資料仍然很痛苦。就通過命令上傳引數,Flask-RESTful 內建了支援驗證請求資料,

from flask.ext.restful import reqparse

parser = reqparse.RequestParser()
parser.add_argument('rate', type=int, help='Rate to charge for this resource')
args = parser.parse_args()

與 argparse 模組不同,reqparse.RequestParser.parse_args() 返回一個 Python 字典而不是一個自定義的資料結構。

使用 reqparse 模組同樣可以自由地提供聰明的錯誤資訊。如果引數沒有通過驗證,Flask-RESTful 將會以一個 400 錯誤請求以及高亮的錯誤資訊迴應。
主要應用在:class Todo中的put(更新引數)、class TodoList中的post(上傳引數)
.

二、如何使用

這邊在官網中提供了兩種方式:一種是curl/一種是利用py的requests

1、curl的方式

# 增加一個新的任務
$ curl http://localhost:5000/todos -d "task=something new" -X POST -v    

#刪除一個任務
$ curl http://localhost:5000/todos/todo2 -X DELETE -v     

#更新一個任務
$ curl http://localhost:5000/todos/todo3 -d "task=something different" -X PUT -v

#獲取一個單獨的任務
$ curl http://localhost:5000/todos/todo3

PUT :更新
POST :新增
.

2、py的requests方式

requests非常強大,本案例所需的有put, get ,post

from requests import put, get ,post
# 更新子任務,todo2
put('http://localhost:5000/todo2', data={'data': 'Change my brakepads'}).json()
{u'todo2': u'Change my brakepads'}

# 拿到子項任務,todo2
get('http://localhost:5000/todo2').json()
{u'todo2': u'Change my brakepads'}

# 看到所有的任務
get('http://localhost:5000/todos').json()

# 新加任務
post('http://localhost:5000/todos', data={'task': 'http://mpic.tiankong.com/5a3/23f/5a323f17880785b60cd4895de11a3569/G70-254989.jpg'}).json()

額外的requests還有以下的請求方式:

r = requests.get("http://httpbin.org/get")
r = requests.post("http://httpbin.org/post")
r = requests.put("http://httpbin.org/put")
r = requests.delete("http://httpbin.org/delete")
r = requests.head("http://httpbin.org/get")
r = requests.options("http://httpbin.org/get")

響應方式有,可以通過多種方式讀取,比如(參考來源:Requests 庫的使用):

  • 普通響應,使用 r.text 獲取,讀取 unicode 形式的響應
  • JSON 響應,使用 r.json() 獲取
  • 二進位制響應,使用 r.content 獲取,獲取二進位制資料,比如用返回的二進位制資料建立一張圖片
  • 原始響應,使用 r.raw 獲取,獲取來自伺服器的原始套接字響應,這可以通過訪問響應物件的 raw 屬性來實現,但要確保在初始請求中設定了 stream=True
    .

延伸一:直接在post中返回結果

    def post(self,api_key):
        api_key_audit(api_key)                                  # 驗證上傳
        args = parser.parse_args()
#        todo_id = int(max(TODOS.keys()).lstrip('todo')) + 1  #lstrip函式是 去掉坐起開始的'todo'字樣
        todo_id = 'todo%i' % len(traverseDirByListdir('../data'))
        save_post_data(todo_id,{todo_id: args['task']})
        return {todo_id: predict(args['task'])}, 201

api.add_resource(TodoList, '/todos/<api_key>')

以上是直接呼叫的一部分內容

# 兩種呼叫方式
post('http://localhost:5000/todos/1', data={'task':url}).json()
! curl http://localhost:5000/todos/1 -d "task=url" -X POST -v    

1為需要驗證的Key。
.

報錯一:

can't find '__main__' module in '' 

把debug關掉app.run(debug=False, ...)
.

延伸二:設定nginx

(1)先找到配置檔案/etc/nginx/nginx.conf的位置

nginx -t 

(2)配置nginx.conf檔案
修改的時候,新加一個:
location /similar {
proxy_pass http://127.0.0.1:6666/Msimilar;
}
即可。

(3)重啟Nginx即可使用
nginx -s reload 重新啟動nginx