Python的Flask框架開發(fā)RESTful API

web框架選擇

  • Django睹酌,流行但是笨重权谁,還麻煩,人生苦短憋沿,肯定不選

  • web.py旺芽,輕量,但據(jù)說(shuō)作者仙逝無(wú)人維護(hù),好吧采章,先pass

  • tornado运嗜,據(jù)說(shuō)倡導(dǎo)自己造輪子,雖然是facebook開源的吧共缕,但聽到這個(gè)洗出,就算了吧

  • flask,輕量图谷,流行翩活,可以自己定義

安裝flask

pip install flask

flask前端模板引擎默認(rèn)是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()

運(yùn)行python app.py便贵,F(xiàn)lask自帶的Server在端口5000上監(jiān)聽:

打開瀏覽器菠镇,輸入首頁(yè)地址http://localhost:5000/

會(huì)出現(xiàn)hello world

簡(jiǎn)單的RESTful實(shí)現(xiàn)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# by vellhe 2017/7/9
from flask import Flask, abort, request, jsonify

app = Flask(__name__)

# 測(cè)試數(shù)據(jù)暫時(shí)存放
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設(shè)置為0.0.0.0,則外網(wǎng)用戶也可以訪問(wèn)到這個(gè)服務(wù)
    app.run(host="0.0.0.0", port=8383, debug=True)

驗(yàn)證結(jié)果

image.png
image.png
image.png

以上是通過(guò)最原始的方式實(shí)現(xiàn)承璃,沒有使用flask的RESTful擴(kuò)展庫(kù)

使用flask的RESTful擴(kuò)展庫(kù) flask-restful

安裝Flask-RESTful庫(kù):

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



# 設(shè)置路由
api.add_resource(TodoList, '/todos')
api.add_resource(Todo, '/todos/<todo_id>')

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

(1)引入需要的庫(kù)名利耍、函數(shù)、變量等盔粹,并做簡(jiǎn)單的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提供了一個(gè)用于參數(shù)解析的RequestParser類隘梨,類似于Python中自帶的argparse類刀诬,可以很方便的解析請(qǐng)求中的-d參數(shù)澈蚌,并進(jìn)行類型轉(zhuǎn)換。

parser = reqparse.RequestParser()
parser.add_argument('task')

(4)我們觀察標(biāo)準(zhǔn)的API接口廓脆,這里的接口可以分為兩類:帶有item_id的进萄,和不帶有item_id的捻脖。前者是操作單一資源,后者是操作資源列表或新建一個(gè)資源中鼠。

從操作單一資源開始可婶,繼承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)繼續(xù)操作資源列表援雇,繼承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)資源操作類定義完畢之后,需要設(shè)置路由熊杨,即告訴Python程序URL的對(duì)應(yīng)關(guān)系曙旭。

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

這樣當(dāng)我們請(qǐng)求url時(shí),就能根據(jù)url類型晶府,找到相應(yīng)的資源類,并調(diào)用對(duì)應(yīng)方法钻趋。

驗(yàn)證結(jié)果

查詢列表:

image.png

查詢單任務(wù):

image.png

刪除任務(wù):

image.png

添加任務(wù)(這是用post表單形式川陆,還可以改成json形式啦):

image.png

更新任務(wù):

image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蛮位,隨后出現(xiàn)的幾起案子较沪,更是在濱河造成了極大的恐慌鳞绕,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,820評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尸曼,死亡現(xiàn)場(chǎng)離奇詭異们何,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)控轿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門冤竹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人茬射,你說(shuō)我怎么就攤上這事鹦蠕。” “怎么了在抛?”我有些...
    開封第一講書人閱讀 168,324評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵钟病,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我刚梭,道長(zhǎng)肠阱,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,714評(píng)論 1 297
  • 正文 為了忘掉前任朴读,我火速辦了婚禮屹徘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘磨德。我一直安慰自己缘回,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評(píng)論 6 397
  • 文/花漫 我一把揭開白布典挑。 她就那樣靜靜地躺著酥宴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪您觉。 梳的紋絲不亂的頭發(fā)上拙寡,一...
    開封第一講書人閱讀 52,328評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音琳水,去河邊找鬼肆糕。 笑死,一個(gè)胖子當(dāng)著我的面吹牛在孝,可吹牛的內(nèi)容都是我干的诚啃。 我是一名探鬼主播,決...
    沈念sama閱讀 40,897評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼私沮,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼始赎!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,804評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤造垛,失蹤者是張志新(化名)和其女友劉穎魔招,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體五辽,經(jīng)...
    沈念sama閱讀 46,345評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡办斑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了杆逗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片乡翅。...
    茶點(diǎn)故事閱讀 40,561評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖髓迎,靈堂內(nèi)的尸體忽然破棺而出峦朗,到底是詐尸還是另有隱情,我是刑警寧澤排龄,帶...
    沈念sama閱讀 36,238評(píng)論 5 350
  • 正文 年R本政府宣布波势,位于F島的核電站,受9級(jí)特大地震影響橄维,放射性物質(zhì)發(fā)生泄漏尺铣。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評(píng)論 3 334
  • 文/蒙蒙 一争舞、第九天 我趴在偏房一處隱蔽的房頂上張望凛忿。 院中可真熱鬧,春花似錦竞川、人聲如沸店溢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)床牧。三九已至,卻和暖如春遭贸,著一層夾襖步出監(jiān)牢的瞬間戈咳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工壕吹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留著蛙,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,983評(píng)論 3 376
  • 正文 我出身青樓耳贬,卻偏偏與公主長(zhǎng)得像踏堡,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子咒劲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容