截至目前為止,使用者的restful已經有個初步的雛形,那接下來要做些甚麼呢?所以今天先重新檢視一下現有的程式碼,雖然昨日的課程把一些驗證請求參數的部份抽離到UserSchema內,不過user.py仍有許多改善的空間,所以今天的內容將一步一步的教授大家如何更進一步重構user.py。
本文章同步放置於此
再接著說明如何重構之前先讓大家看看截至目前的程式碼。
from flask_restful import Resource
from flask import request
from models.schema.user import UserSchema
users = []
user_schema = UserSchema()
class User (Resource):
def get(self, name):
find = [item for item in users if item['name'] == name]
if len(find) == 0:
return {
'message': 'username not exist!'
}, 403
user = find[0]
if not user:
return {
'message': 'username not exist!'
}, 403
return {
'message': '',
'user': user
}
def post(self, name):
result = user_schema.load(request.json)
if len(result.errors) > 0:
return result.errors, 433
user = {
'name': name,
'email': result.data['email'],
'password': result.data['password']
}
global users
users.append(user)
return {
'message': 'Insert user success',
'user': user
}
def put(self, name):
result = user_schema.load(request.json)
if len(result.errors) > 0:
return result.errors, 433
find = [item for item in users if item['name'] == name]
if len(find) == 0:
return {
'message': 'username not exist!'
}, 403
user = find[0]
user['email'] = result.data['email']
user['password'] = result.data['password']
return {
'message': 'Update user success',
'user': user
}
def delete(self, name):
global users
users = [item for item in users if item['name'] != name]
return {
'message': 'Delete done!'
}
class Users(Resource):
def get(self):
return {
'message': '',
'users': users
}
首先先將使用者相關的函式抽離User這個Resource,而且將users這變數也放到models.user.py內,所以我們重構的第一個步驟就是產生含有以下內容的models.user.py:
users = []
class UserModel:
name = ''
email = ''
password = ''
def __init__(self, name, email, password):
self.name = name
self.email = email
self.password = password
def add_user(self):
users.append(self)
@staticmethod
def get_user(name):
find = [item for item in users if item.name == name]
if len(find) == 0:
return None
return find[0]
@staticmethod
def delete_user(name):
global users
users = [item for item in users if item.name != name]
@staticmethod
def get_all_user():
return users
在抽離使用者相關的函式之後,我們首先整理User這個Resource,簡單來說就是把相同的動作以呼叫models.user來取代,但是在返還客戶端會遇到Model解析的問題,因為我們之前的使用者資料都是返回dict格式,所以flask-restful會自動轉換為JSON格式,但是現在的使用者資料是UserModel所以返還時無法解析,這時再透過flask-marshmallow來處理即可,處理的方式如下列說明:
user_schema.dump(user).data
最後user修改後結果如下:
from flask_restful import Resource
from flask import request
from models.schema.user import UserSchema
from models.user import UserModel
user_schema = UserSchema(many=False)
class User (Resource):
def get(self, name):
user = UserModel.get_user(name)
if not user:
return {
'message': 'username not exist!'
}, 403
return {
'message': '',
'user': user_schema.dump(user).data
}
def post(self, name):
result = user_schema.load(request.json)
if len(result.errors) > 0:
return result.errors, 433
user = UserModel(name, result.data['email'], result.data['password'])
user.add_user()
return {
'message': 'Insert user success',
'user': user_schema.dump(user).data
}
def put(self, name):
result = user_schema.load(request.json)
if len(result.errors) > 0:
return result.errors, 433
user = UserModel.get_user(name)
if not user:
return {
'message': 'username not exist!'
}, 403
user.email = result.data['email']
user.password = result.data['password']
return {
'message': 'Update user success',
'user': user_schema.dump(user).data
}
def delete(self, name):
UserModel.delete_user(name)
return {
'message': 'Delete done!'
}
class Users(Resource):
def get(self):
return {
'message': '',
'users': user_schema.dump(UserModel.get_all_user(), True).data
}
在抽離公同函式之後,我們可以針對已知問題加以改善,所以這邊我們在針對POST與PUT都在處理請求參數的部分抽離共同函式來處理,而相關改善的程式碼如下所示:
def get_param():
data = request.get_json(force=False)
if data is None:
data = request.form
return data
在完成使用者的CRUD後我們改進了請求參數的方式,今日又抽離共同方法,將原本的使用者Resource重構並改善其功能。接下來的工作就是導入db,讓既有的使用者資料存放在資料庫中,敬請期待。
版主您好,我在執行POST中
此行 result = user_schema.load(request.json) 會顯示錯誤
看起來主要原因是
marshmallow.exceptions.ValidationError: {'_schema': ['Invalid input type.']}
想請問該如何修正呢?
你可以看一下前一篇,然後檢查一下你post的型別跟定義的是否相符
我都是照著文章的方式寫,基本上完全依樣
但執行還是遇到此問題
嘗試將(request.json) print出來,會是NULL