Flask之REST&API設計

Flask之REST&API設計

一、REST(一種軟件架構(gòu)風格)?

?一)、問題?

?網(wǎng)絡應用程序,分為前端和后端兩個部分。當前的發(fā)展趨勢,就是前端設備層出不窮(手機、平板、桌面電腦、其他專用設備......)。?

?因此,必須有一種統(tǒng)一的機制,方便不同的前端設備與后端進行通信。這致使API構(gòu)架的流行。

?二)、基本概念

?REST是"Representational State Transfer"縮寫,即是"表現(xiàn)層狀態(tài)轉(zhuǎn)化"。而"表現(xiàn)層"其實指的是"資源(Resource)"的表現(xiàn)層。

?一種軟件構(gòu)架風格,設計風格,而不是標準,只是提供了一組設計原則和約束條件。

它主要用于客戶端和服務端交互的軟件?;谶@個風格設計的軟件可以更簡潔,更有層次,更易于實現(xiàn)緩存機制等。

?REST其實是一種組織Web服務的架構(gòu),而并不是我們想象的那樣是實現(xiàn)Web服務的一種新的技術(shù),更沒有要求一定要使用HTTP。其目標是為了創(chuàng)建具有良好擴展性的分布式系統(tǒng)。

1. 資源(Resource) 就是網(wǎng)絡上的一個實體,或是網(wǎng)絡上的具體信息,可以是一段文本、一張圖片、一首歌曲、一部電影。 每個資源都會對應的URL,且是唯一的標識符,想要獲取資源只需要調(diào)用對應URL。

2. 表現(xiàn)層(Representation) "資源"是一種信息實體,它可以有多種外在表現(xiàn)形式。 而"資源"具體呈現(xiàn)出來的形式,就叫它的"表現(xiàn)層"。

3. 狀態(tài)轉(zhuǎn)換(State Transfer) 訪問一個網(wǎng)站,就是客戶端和服務端的交互過程,這個過程中就會涉及到數(shù)據(jù)和狀態(tài)的變化。 互聯(lián)網(wǎng)通信協(xié)議HTTP,是無狀態(tài)協(xié)議。即所有狀態(tài)都保存在服務端。?

?客戶端要操作服務端必須通過某種方式,讓服務端發(fā)生"狀態(tài)轉(zhuǎn)換",而這轉(zhuǎn)換是建立在表現(xiàn)層之上的,所以就是"表現(xiàn)層狀態(tài)轉(zhuǎn)換"。?

?客戶端用到的手段只能是HTTP協(xié)議,在操作方式的動詞:?

?GET/POST/PUT/DELETE。

?對應GET獲取資源,

POST新建資源(或更新資源),

PUT更新資源,

DELETE刪除資源。

?三)、構(gòu)架級約束

1.使用客戶/服務器模型??蛻艉头掌髦g通過一個統(tǒng)一的接口來互相通訊

2.層次化的系統(tǒng)。在一個REST系統(tǒng)中,客戶端并不會固定地與一個服務器打交道

3.無狀態(tài)。在一個REST系統(tǒng)中,服務端并不會保存有關(guān)客戶的任何狀態(tài)。也就是說,客戶端自身負責用戶狀態(tài)的維持,并在每次發(fā)送請求時都需要提供足夠的信息

4.可緩存。REST系統(tǒng)需要能夠恰當?shù)鼐彺嬲埱?,以盡量減少服務端和客戶端之間的信息傳輸,以提高性能

5.統(tǒng)一的接口。一個REST系統(tǒng)需要使用一個統(tǒng)一的接口來完成子系統(tǒng)之間以及服務與用戶之間的交互。這使得REST系統(tǒng)中的各個子系統(tǒng)可以獨自完成演化?

?注意:一個系統(tǒng)滿足了上面所列出的五條約束,那么該系統(tǒng)就被稱為是RESTful

二、RESTful API設計

?一)、協(xié)議 API與用戶通信協(xié)議,通常使用HTTP(S)協(xié)議。

?二)、域名應該盡量將API部署在專用域名之下。 如:http://api.zyz.com 如果確定API很簡單,不會有大規(guī)模擴充??梢钥紤]放在 主域名之下。如:http://www.zyz.com/api/

?三)、版本 應該將API的版本號放入URL。

?如:http://api.zyz.com/v1/ 也有將版本號放在HTTP的頭信息中,但不如放在URL中方便直觀,Github就是這么做的。

?四)、路徑路徑又稱"終點"(endpoint),表示API的具體網(wǎng)址。在RESTful架構(gòu)中,每個網(wǎng)址代表一種資源,所以網(wǎng)址不能有動詞,只能有名詞。而所用名詞往往與數(shù)據(jù)庫表單名對應。

?五)、HTTP動詞對于資源的具體操作類型,由HTTP動詞表示。

HTTP常用動詞:?

?- GET(SELECT) 從服務器取資源?

?- POST(CREATE or UPDATE) 服務器中創(chuàng)建資源或更新資源?

?- PUT(UPDATE) 在服務器更新資源(客戶端提供改變后的完整資源)?

?- PATCH(UPDATE) 在服務器更新資源(客戶端提供改變的屬性)?

?- DELETE(DELETE) 從服務器刪除資源 - HEAD 獲取資源的元數(shù)據(jù)

?- OPTHONS 獲取信息,關(guān)于資源的那些屬性是客戶端可以改變的例如:?

?- GET /students 獲取所有學生?

?- POST /student 新建學生?

?- GET /students/id 獲取某一個學生

?- PUT /students/id 更新某個學生的信息(需要提供學生的全部信息)

?- PATHC /students/id 更新某個學生的信息(需要提供學生變更信息) - DELETE /students/id 刪除某個學生

?六)、過濾信息當記錄數(shù)量過多,服務器不可能將它們返回給用戶。

APIT應該提供參數(shù),過濾返回結(jié)果。 ?limit=10 ?offset=10 ?page=2&per_page=10 ?sortby=name&order=desc ?student_id=id?

?七)、狀態(tài)碼

?服務器向用戶返回的狀態(tài)碼和提示信息。?

00 OK - [GET]:服務器成功返回用戶請求的數(shù)據(jù) 201 CREATED -[POST/PUT/PATCH]:用戶新建或修改數(shù)據(jù)成功?

?202 Accepted - [*] :表示一個請求已經(jīng)進入后臺排隊(異步任務)?

?204 NO CONTENT - [DELETE]:表示數(shù)據(jù)刪除成功?

?400 INVALID REQUEST - [POST/PUT/PATCH]:用戶發(fā)出的請求有錯誤?

?401 Unauthorized - [*] :表示用戶沒有權(quán)限(令牌,用戶名,密碼錯誤)?

?403 Forbidden - [*]:表示用戶得到授權(quán),但是訪問是被禁止的?

?404 NOT FOUND - [*]:用戶發(fā)出的請求針對的是不存在的記錄?

?406 Not Acceptable - [*]:用戶請求格式不可得 410 Gone - [GET] :用戶請求的資源被永久移除,且不會再得到的?

?422 Unprocesable entity -[POST/PUT/PATCH]:當創(chuàng)建一個對象時,發(fā)生一個驗證錯誤

500 INTERNAL SERVER EROR - [*] :服務器內(nèi)部發(fā)生錯誤?

?2xx —— 正確的響應?

?3xx —— 重定向?

?4xx —— 客戶端錯誤?

?5xx —— 服務端錯誤

八)、返回結(jié)果

錯誤處理:

如果狀態(tài)碼是4xx,就應該向客戶端返回出錯信息,一般來說,返回信息中將error作為鍵名?

?針對不同操作,服務器向用戶返回的結(jié)果應符合一下規(guī)范:?

?GET /collection:返回資源對象的列表(數(shù)組,集合)?

?GET /collection/id:返回單個資源對象?

?POST /collection:返回新生成的資源對象?

?PUT /collection/id:返回完整的資源對象?

?PATCH /collection/id:返回完整的資源對象 DELETE /collection/id:返回一個空文檔注意:服務器返回的數(shù)據(jù)格式,應該盡量是JSON?

?九)、原生實現(xiàn)數(shù)據(jù)和狀態(tài)的返回@blue.route('/user/',methods=['POST','GET','PUT','DELETE','PATCH'])

def user(userid):?

?if request.method == 'GET': # 獲取用戶?

?????pass

elif request.method == 'POST': # 更新或創(chuàng)建用戶密碼

# 獲取數(shù)據(jù)

username = request.form.get('username')

password = request.form.get('password')

data = {?

?????????'msg':'ok',?

?????????'status': 201

}\

? ? ? # 不為空

? ? ? ? if not username or not password:?

?????????????data['msg'] = '參數(shù)不正確'?

?????????????data['status'] = 422 return jsonify(data),422

????user = User()

? ? ?user.u_name = username

? ? ? user.u_passwd = generate_passwd(password)

????try:?

?????????db.session.add(user)?

?????????db.session.commit()

????except Exception as e:?

?????????data['msg'] = '用戶已存在'?

?????????data['status'] = 423?

?????????return jsonify(data), 423

? ? return jsonify(data),201?

?elif request.method == 'DELETE': # 刪除用戶

????????????????pass

elif request.method == 'PUT': # 更新賬和密碼

????????????????pass?

?elif request.method == 'PATCH': # 修改密碼

????????????????pass

else:

????????????????abort(405)?

?# 密碼加密處理?

?def generate_passwd(passwd):?

?????????hash = hashlib.md5() ????????hash.update(passwd.encode('utf-8'))?

?????return hash.hexdigest()

三、Flask-RESTful插件

?Flask-RESTful添加快速構(gòu)建REST API的支持,也是一個能夠和現(xiàn)有的ORM庫協(xié)同工作的輕量級的擴展。Flask-RESTful鼓勵以最小的設置的最佳實踐。

?一)、基本使用 安裝 pip install flask-restful?

?相關(guān)文檔:http://www.pythondoc.com/Flask-RESTful/quickstart.html?

?配置?

?#ext.py文件中?

?from flask-restful import Api?

?api = Api()

使用?

?# 定義一個資源 # views.py 已經(jīng)可以替換為apis.py,之前的路由功能換種寫法?

?class HelloWorld(Resource):

?????def get(self): # get 請求

?????return {

????????'msg':'hello world'

????????}

????def post(self): #post請求

?????return {

????????'msg':'你好!????

????????'}?

?#添加一個資源?

?#ext.py文件中?

?#add_resource 注冊路由到框架上

?#如果沒有指定 endpoint,Flask-RESTful會根據(jù)類名生成一個?

?#但有時候如 url_for 需要 endpoint ,因次最好明確給 endopint 賦值

?api.add_redource(HelloWorld,'/hello/',endopint ='hello')?

?備注:之前路的操作都是在views.py中,現(xiàn)在只需要提供API借口,所以功能就會不一樣。?

?在項目進行完基本的拆分之后,可以將views.py改變api.py。

注意:Flask-RES-JSON插件,F(xiàn)lask-RESTless插件?

?二)、帶參數(shù)操作

?#apis.py?

?class UserAPI(Resource):?

????def get(self,userid):?

?????????str = '(get)userid: %d' % userid?

?????????return {

????????????'msg':str

????????????}?

?????def post(self,id):

?????????str = '(post)userid: %d' %id

?????????return {

????????????'msg':str

????????????}?

?????#ext.py 文件

?????from App.apis import UserAPI ????????api.add_resource(UserAPI,'/user//',endopint='user')

? ? ? 注意:Flask-RESTful提供的最主要的基礎是資源(resources)。資源(Resources)是構(gòu)建在Flask試圖之上,只要在你的資源(resource)上定義方法就能夠容易地訪問 多個HTTP方法。[無需原生操作,因為一個資源而進行不同的判斷操作處理]

? ? 三)、端點操作(Endopints)

很多時候在一個 API 中,你的資源可以通過多個 URL 訪問。

? ? ? ? 你可以把 多個 URL傳給 Api對象 Api.add_resource()方法。每個URL都能訪問到你的 Resource.

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

? ? 四)、輸出格式定制

默認情況下,在你返回的迭代中所有字段將會原樣呈現(xiàn)。

實際更多的需要一個字典類型數(shù)據(jù),之后通過 JSON序列化即可。

Flask-RESTful 提供了 fields模塊和 marshal_with() 裝飾器來進行數(shù)據(jù)格式化。

? ? ? ? # @marshal_with(需要返回的數(shù)據(jù)格式)

? 如果返回的數(shù)據(jù),在預定義的結(jié)構(gòu)中不存在,會被自動過濾掉;

? 如果返回的數(shù)據(jù),在預定義的結(jié)構(gòu)中存在,數(shù)據(jù)會正常返回;

? 如果返回的數(shù)據(jù)比預定義的結(jié)構(gòu)字段少,預定義的字段會顯示默認值;

? #支持類型

常用基本類型

String

Integer

類表類型

List

級聯(lián)類型

Nested

結(jié)構(gòu)嵌套

fields.List(fields.Nesred())

? # 示例1

"""獲取一只貓的數(shù)據(jù)基本結(jié)構(gòu)

? {

????'msg':'ok',

????'status':200,

????'data':{

????'id':1,

????'name':'TOM',

????'color':'紅色'

????}

}

"""


? ? catmodel_fields = {

????????????'id':fields.Integer,

????????????'name':fields.String,

????????????'color':fields.String

}

onecar_fields = {

????????????'msg': fields.String(default='ok'),

????????????'status': fields.Integer(default=200),

????????????'data': fields.Nested(catmodel_fields)? # 嵌套

? ? }


? ? class OneCatResource(Resource):

????@marshal_with(onecar_fields)

????def get(self):

? ? ????cat = Cat.query.first()

? ? ????????data = {

???????????????????# msg 使用默認值,可以省略不寫

? ? ? ? ? ? ? ? ?# status 使用默認只,也可以不寫

????????????????????'data': cat

? ????? }

? ? return data

# 示例2

? ? """ 獲取所有貓的數(shù)據(jù)結(jié)構(gòu)

????{

? ? ????'msg':'ok',

? ????? 'status': 200,

? ????? 'data': [

????????????{

? ? ????????????'id': 1,

? ????????????? 'name': 'TOM1',

? ????????????? 'color': '紅色'

????},

????{

? ? ????????'id': 2,

? ? ????????'name': 'TOM2',

? ?????????'color': '紅色'

????},

????{

? ? ????????'id': 3,

? ? ????????'name': 'TOM3',

? ? ????????'color': '紅色'

????},

...

? ? ]

}

? ? """

? ? catmodel_fields = {

????????????'id': fields.Integer,

????????????'name': fields.String,

????????????'color': fields.String

? ? }


? ? cats_fields = {

????????????'msg': fields.String(default='ok'),

????????????'status': fields.Integer(default=200),

????????????'data': fields.List(fields.Nested(catmodel_fields))

? ? }

? ? class CatResource(Resource):

????@marshal_with(cats_fields)

????def get(self):

? ? ????cats = Cat.query.all()

? ? ? ? ?data = {

????????????'msg': 'ok!',

????????????'status': 200,

????????????'data': cats

? ????? }

? ????? return data

? ? 五)、請求參數(shù)解析

基本使用

# https://127.0.0.1/showview/?page=1

parser = reqparse.RequestParser()

#接受參數(shù)page,類型是str,錯誤提示help

parser.add_argument('page',type=str,help='請輸入頁碼')

class ShouView(Resource):

? ? def? get(self):

parser = parser.parse_args()

? ? ? ? c_page = parser.get('page') or 1

? ? def post(self):

? parser = parser.parse_args()

? c_page = parser.get('page') or 1

? ? ? ? 必須參數(shù) required = Ture

? # 請求參數(shù)必須傳入

? parser.add_argument('page', type=int, help='請輸入頁碼', required=True)

多參數(shù)(列表)

? ? # 如果要接受一個鍵有多個值的話,可以傳入 action='append'

? ? # https://127.0.0.1/showview/?name='liming'&page=1&name='zhangsan'

? ? parser.add_argument('name', type=str, action='append')

參數(shù)位置

? ? 參數(shù)位置: form、args、headers、cookies、files(上傳文件)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、REST 問題 網(wǎng)絡應用程序,分為前端和后端兩個部分。當前的發(fā)展趨勢,就是前端設備層出不窮(手機、平板、桌面電...
    EndEvent閱讀 2,349評論 0 4
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,688評論 19 139
  • 一篇好的關(guān)于RESTFUL API的文章(對英文進行了簡單的翻譯,方便英文閱讀困難的朋友),共讀,閱讀時間約10分...
    CC先生之簡書閱讀 2,811評論 0 7
  • 一般來講 風熱犯肺、熱邪蘊肺都屬于肺熱。風熱犯肺 多見冬春季節(jié),主要癥狀咳嗽、咯黃痰,可有鼻塞流黃涕,口干,咽喉痛...
    寶貝兒公主閱讀 2,507評論 0 0
  • 步驟網(wǎng)上很多資料都有,我也是跟著大神們的腳步來的, 但是發(fā)現(xiàn)跟著官網(wǎng)來其實更好flutter官網(wǎng) 1.因為是在 中...
    阿牛_6a83閱讀 347評論 0 0

友情鏈接更多精彩內(nèi)容