REST API設(shè)計(jì)的核心是資源(Resource)嗤栓,圍繞著資源才有了URI和各種各樣的HTTP操作。
因此,如何對(duì)資源建模就顯得十分重要澜躺,
這關(guān)系到API能否為使用者提供他們想要的功能桩蓉,
以及API的設(shè)計(jì)是否簡(jiǎn)明淋纲,便于維護(hù)。
資源和資源列表的URI
資源可以是獨(dú)立的院究,比如每個(gè)單獨(dú)的用戶user
洽瞬。
也可以是一個(gè)集合玷或,比如所有的用戶users
。
在用復(fù)數(shù)表示資源集合時(shí)片任,
可以對(duì)整個(gè)資源列表進(jìn)行操作:
GET /users
也可以通過集合下單獨(dú)個(gè)體的ID來獲取具體某個(gè)資源:
GET /users/{userId}
偏友。
資源和資源列表的互相嵌套
這種“單個(gè)資源”與“資源列表”還可以繼續(xù)互相嵌套下去,
比如每個(gè)用戶可能有不止一個(gè)賬號(hào):
/users/{userId}/accounts/{accountId}
資源和資源列表的建模
在數(shù)據(jù)建模時(shí)对供,
可以將資源列表對(duì)應(yīng)整個(gè)存儲(chǔ)該類型資源的表格位他,
將單個(gè)資源對(duì)應(yīng)表格中的每一行。
以Flask-SQLAlchemy
為例产场,
定義UserModel
對(duì)應(yīng)所有用戶的集合鹅髓,映射整個(gè)存儲(chǔ)用戶的表格:
# models/user.py
class UserModel(db.Model):
__tablename__ = 'users'
@classmethod
def find_by_name(cls, id):
return cls.query.filter_by(id=id).first()
資源和資源列表的定義
如上文所示,
整個(gè)資源集合被一同建模京景,對(duì)應(yīng)底層數(shù)據(jù)庫的一個(gè)表格窿冯。
但如果我們想通過URI對(duì)單個(gè)資源和資源列表分別進(jìn)行操作,
GET /users
GET /users/{userId}
最好在使用Flask-SQLAlchemy
庫進(jìn)行資源定義時(shí)确徙,
對(duì)單個(gè)資源和資源列表進(jìn)行分別定義:
# resources/user.py
from flask_restful import Resource
from models.user import UserModel
class User(Resource):
def get(self, id):
user = UserModel.find_by_id(id)
if user:
return user.json(), 200
return {'message': 'User not found'}, 404
class UserList(Resource):
def get(self):
return {'users': list(map(lambda x: x.json(), UserModel.query.all()))}
用戶在使用API時(shí)醒串,
既可以對(duì)user
資源進(jìn)行操作,
通過提供不同的userId
查找對(duì)應(yīng)的用戶鄙皇,
也可以對(duì)userList
資源(即user
的資源列表)進(jìn)行操作芜赌,
返回所有的用戶。
但不管是user
還是userList
伴逸,
都只與同一個(gè)模型:userModel
進(jìn)行交互缠沈。
對(duì)應(yīng)到底層數(shù)據(jù)庫也是一樣,
都只對(duì)table users
進(jìn)行操作错蝴,
區(qū)別只是返回整個(gè)表格洲愤,
還是返回特定的某一行。
對(duì)資源和資源列表操作的分配
既然對(duì)同一種資源顷锰,
現(xiàn)在有了“單個(gè)資源”與“資源列表”兩個(gè)并行的資源類柬赐,
對(duì)資源的各種操作就需要合理地分配到這兩個(gè)類中。
比如對(duì)單個(gè)資源的獲取馍惹,更新和刪除躺率,
適合放在“單個(gè)資源”的資源類下。
對(duì)資源集合的整體獲取万矾,和添加新的資源悼吱,
適合放在“資源列表”的資源類下。