第十屆鐵人賽 flask-restful DAY21-搞懂flask-restful Resource的重構

重構Resource

截至目前為止,使用者的restful已經有個初步的雛形,那接下來要做些甚麼呢?所以今天先重新檢視一下現有的程式碼,雖然昨日的課程把一些驗證請求參數的部份抽離到UserSchema內,不過user.py仍有許多改善的空間,所以今天的內容將一步一步的教授大家如何更進一步重構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.py

首先先將使用者相關的函式抽離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

在抽離使用者相關的函式之後,我們首先整理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,讓既有的使用者資料存放在資料庫中,敬請期待。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *