Flask開發技巧之引數校驗

luyuze95發表於2020-12-11

Flask開發技巧之引數校驗

本人平時開發中使用的,或者學習到的一些flask開發技巧整理,需要已有較為紮實的flask基礎。

1、請求引數分類

一般來說,前端傳送過來的請求中,大致包含以下三種型別的引數,分別是url路徑引數,url查詢引數,還有目前前後端分離開發中最常見的json格式的資料。

  • url路徑引數
/v1/user/1

url路徑引數即類似於上述例子中的引數,直接帶在url路徑中,可變化,flask針對這種引數,已經直接提供了支援,例:

@app.route('/v1/user/<int:id>')
  • url查詢引數
/v1/user?page=1&pageSize=10

類似於這種帶在url中的問號後面的鍵值對並且用&連線的引數稱為url查詢引數

  • json格式的引數
{
    "name": "xiaowang",
    "age": 1
}

而json格式的引數就更不用多說了,header中帶有Content-Type:Application/json傳輸過來的json格式的資料就是這樣的。

2、解決方案使用到的庫

這裡我們為了解決引數校驗的問題,一定是要將引數校驗的部分抽離出來,按照物件導向的思想,隱藏引數校驗的具體過程,交給特定的類去解決。這樣,我們在檢視函式中,不會出現冗餘的引數校驗程式碼,會使整個檢視函式顯得簡短易讀。

這裡我們需要安裝兩個庫

pip install WTForms
pip install WTForms-JSON

後續方法建立在wtforms庫上擴充套件,所有wtforms庫原有的操作,全部都有效,可以繼續使用。如果不熟悉wtforms,需要先學習一下。

3、針對url查詢引數與一般json格式

首先解釋一下,經過我的探究(本人能力有限,可能無法擴充套件實現),使用普通的wtforms庫,無法接受複雜格式的json資料,只能接受普通格式的json資料以及url查詢引數進行校驗。

  • 普通格式的json引數舉例
{
    "name": "xiaowang",
    "age": 1,
    "address": "beijing"
}
  • 複雜格式的json引數舉例
{
    "category": {
        "category_name": "電腦",
        "category_id": 2
    },
    "address_list": [
        "beijing",
        "shanghai"
    ]
    "name": "xiaohong",
    "age": 1,
}

實現方法,繼承wtforms庫中的Form,實現自己的基類引數驗證類BaseForm

class BaseForm(Form):
    def __init__(self):
        data = request.get_json()
        args = request.args.to_dict()
        super(BaseForm, self).__init__(data=data, **args)

    def validate_for_api(self):
        valid = super(BaseForm, self).validate()
        if not valid:
            raise ParameterException(msg=self.errors)
        return self

這裡進行一下說明,BaseForm的__init__方法例項化物件的時候首先通過flask中的request物件將普通json資料和查詢引數args拿到,通過呼叫父類的方法將引數初始化。

而validate_for_api()方法則呼叫父類中的validate()進行引數校驗,如果校驗結果不通過,那麼將錯誤資訊放入msg交給異常類400處理,異常處理我們已經在上一篇詳細講述。如果校驗通過,那麼就將校驗完成的form返回。

使用舉例

針對一個請求url為

/v1/user?user_id=1

請求體為

{
    "username": "xiaoming",
    "age": 1
}

那麼使用如下類:

class UserForm(BaseForm):
    user_id = IntegerField()
    username = StringField()
    age = IntegerField()


form = UserForm().validate_for_api()

即可完成引數校驗,如果校驗出錯,會直接向前端返回400,並且錯誤資訊也會附帶返回。

4、針對複雜json格式資料

單純的使用wtforms庫無法實現複雜json格式資料的處理,於是在我的探索下,發現還有一個wtforms的擴充套件庫,叫wtforms-json,通過這個庫可以實現。

於是擴充套件原先的BaseForm,使用wtforms-json,仿照原先基類,我實現的新基類如下。

import wtforms_json

class JsonForm(Form):

    @classmethod
    def init_and_validate(cls):
        wtforms_json.init()
        form = cls.from_json(request.get_json())
        valid = form.validate()
        if not valid:
            raise ParameterException(msg=form.errors)
        return form

繼承上述新的基類,這樣的Form就可以實現任意json格式的資料的校驗了。

使用舉例

針對一個請求,請求體如果為

{
    "username": "xiaochen",
    "age": 1,
    "address_list": [
        "beijing",
        "shanghai"
    ],
    "info": {
        "name": "hi",
        "length": 5
    },
    "area_list": [
        {
            "level1": "北京",
            "level2": "朝陽"
        },
        {
            "level1": "北京",
            "level2": "海淀"
        }
    ]
}

通過如下Form就可以實現校驗

class InfoForm(JsonForm):
    name = StringField()
    length = IntegerField()

class AreaForm(JsonForm):
    level1 = StringField()
    levle2 = StringField()

class DemoForm(JsonForm):
    username = StringField()
    age = IntegerField()
    address_list = FieldList(
        StringField(),
        min_entries=1
    )
    info = FormField(InfoForm)
    area_list = FieldList(
        FormField(AreaForm),
        min_entries=1
    )


form = DemoForm().init_and_validate()

如此就可以實現複雜json資料的校驗

關於flask的引數校驗,以上就是我目前掌握的一些技巧,如有錯誤歡迎指出。


部落格園: https://www.cnblogs.com/luyuze95/

GitHub: https://github.com/luyuze95

相關文章