注意:Flask-RESTPlus的整個請求解析器部分將被移除,並將替換成關於集成其餘更善於處理輸入、輸出的包(例如marshmallow)的說明文檔。可是考慮到已經被廢棄,它將一直維護到2.0版本。若是你如今有代碼使用它,並但願繼續這樣作,那麼也無需擔憂,由於它不會很快消失。html
Flask-RESTPlus的請求解析接口reqparse是模仿argparse接口實現的。它的設計目的是對Flask中flask.request對象上的任何變量提供簡單和統一的訪問方式。git
下面是一個請求解析器的簡單示例。它在flask.Request.values字典中查找兩個參數:一個整數和一個字符串:github
from flask_restplus import reqparse parser = reqparse.RequestParser() parser.add_argument('rate', type=int, help='Rate cannot be converted') parser.add_argument('name') # Python3中默認類型爲字符串 args = parser.parse_args()
注意:默認參數類型是unicode字符串。在Python3中爲str類型,而在Python2中爲unicode。json
若是指定了help變量的值,那麼在解析請求時,若是出現了類型錯誤,那麼會將它渲染爲錯誤信息。若是未指定help信息,那麼默認的行爲是返回類型錯誤信息自己。能夠查看「十一、錯誤信息」部分以瞭解更多細節。flask
注意:默認狀況下,參數不是必需的。而且,若是請求中提供的某些參數不是RequestParser的部份內容,那麼這些參數將會被忽略。api
注意:請求解析器中聲明的參數,若是在請求中並未設置這些參數值,那麼它們將會默認設置爲None。restful
若是須要確保某個參數必須提供,那麼能夠在調用add_argument()時傳入required=True的參數項:cookie
parser.add_argument('name', required=True, help="Name cannot be blank!")
此時,若是請求中未提供該參數,那麼將會返回錯誤信息。session
若是想爲某個key接受多個值以構成列表,那麼能夠傳入action='append':app
parser.add_argument('name', action='append')
此時的查詢格式以下所示:
curl http://api.example.com -d "name=bob" -d "name=sue" -d "name=joe"
而程序中獲取到的參數以下所示:
args = parser.parse_args() args['name'] # ['bob', 'sue', 'joe']
若是指望一個逗號分隔的列表,那麼可使用action='split':
parser.add_argument('fruits', action='split')
此時的查詢格式以下所示:
curl http://api.example.com -d "fruits=apple,lemon,cherry"
而程序中獲取到的參數以下所示:
args = parser.parse_args() args['fruits'] # ['apple', 'lemon', 'cherry']
若是指望參數一旦被解析,就將其存儲爲其餘名字,那麼可使用dest參數:
parser.add_argument('name', dest='public_name') args = parser.parse_args() args['public_name']
默認狀況下,RequestParser嘗試從flask.Request.values和flask.Request.json中解析值。
在add_argument()中使用location參數來指定獲取值的其餘位置。可使用flask.Request上的任何變量,例如:
# 僅僅在POST body中查找 parser.add_argument('name', type=int, location='form') # 僅僅在querystring中查找 parser.add_argument('PageSize', type=int, location='args') # 從請求頭中查找 parser.add_argument('User-Agent', location='headers') # 從http cookies中查找 parser.add_argument('session_id', location='cookies') # 從上傳文件中查找 parser.add_argument('picture', type=werkzeug.datastructures.FileStorage, location='files')
注意:當location='json'時只能使用type=list,點擊此處查看更多。
注意:使用location='form'既能驗證表單數據,又能爲表單字段文檔化。
爲location參數賦一個列表就能爲參數指定多個位置:
parser.add_argument('text', location=['headers', 'values'])
當指定多個參數位置時,那麼全部指定位置的參數將會組成一個MultiDict。其中,列表中最後位置處的參數將會優先存儲在結果集中。
若是參數位置列表中包含headers位置,那麼參數名將變成對大小寫敏感,而且必須匹配它們的標題大小寫名稱(見str.title())。
指定location='headers'(而不是做爲列表的某個元素)將保留大小寫不敏感的特性。
有時,咱們須要其餘原始類型來處理輸入驗證問題。爲此,inputs模塊中提供了一些經常使用的類型處理方法,以下:
只須要使用它們做爲type參數的值便可:
parser.add_argument('flag', type=inputs.boolean)
查看inputs文檔以瞭解全部可用的輸入類型。
另外,咱們也能夠編寫本身的輸入類型:
def my_type(value): '''解析類型''' if not condition: raise ValueError('This is not my type') return parse(value) # Swagger文檔化 my_type.__schema__ = {'type': 'string', 'format': 'my-custom-format'}
不少狀況下,咱們都須要爲不一樣的資源指定不一樣的解析器。不過,若是這些不一樣的解析器之間存在大量相同的字段的話,將會存在大量重複編碼的問題。爲此,咱們能夠編寫一個父解析器,父解析器中包含全部共同的參數,而後利用copy()方法來擴展解析器。另外,也能夠利用replace_argument()來覆寫父解析器中的任何參數,或者利用remove_argument()徹底移除父解析器中的某個參數。例如:
from flask_restplus import reqparse parser = reqparse.RequestParser() parser.add_argument('foo', type=int) parser_copy = parser.copy() parser_copy.add_argument('bar', type=int) # 此時,parser_copy中同時包含'foo'和'bar'參數 parser_copy.replace_argument('foo', required=True, location='json') # 此時,'foo'參數變成了一個必需的str類型的參數,而且查找位置爲json;而再也不是父解析器中定義的int類型的可選參數 parser_copy.remove_argument('foo') # 此時,parser_copy中再也不包含'foo'參數
爲了利用RequestParser處理文件上傳問題,咱們須要將location變量值設置爲files,並設置type值爲FileStorage。以下所示:
from werkzeug.datastructures import FileStorage upload_parser = api.parser() upload_parser.add_argument('file', location='files', type=FileStorage, required=True) @api.route('/upload/') @api.expect(upload_parser) class Upload(Resource): def post(self): uploaded_file = args['file'] # 這是FileStorage實例 url = do_something_with_file(uploaded_file) return {'url': url}, 201
RequestParser處理錯誤的默認方式是在第一個錯誤產生時中斷。當咱們擁有須要花費必定時間來處理的參數時,這種方式是有好處的。然而,一般來講,將全部產生的錯誤都綁定在一塊兒,而後同時一次性返回給客戶端,這種方式則更加友好。這種方式既能夠在Flask應用級別指定,也能夠在特定的RequestParser實例級別指定。爲了調用一個包含錯誤綁定選項的RequestParser,須要傳入參數bundle_errors。例如:
from flask_restplus import reqparse parser = reqparse.RequestParser(bundle_errors=True) parser.add_argument('foo', type=int, required=True) parser.add_argument('bar', type=int, required=True) # 若是某個請求中同時不包含'foo'和'bar',那麼返回的錯誤將看起來以下所示: { "message": { "foo": "foo error message", "bar": "bar error message" } } # 默認操做將僅僅返回第一個錯誤 parser = RequestParser() parser.add_argument('foo', type=int, required=True) parser.add_argument('bar', type=int, required=True) { "message": { "foo": "foo error message" } }
應用級別的配置key爲「BUNDLE_ERRORS」。例如:
from flask import Flask app = Flask(__name__) app.config['BUNDLE_ERRORS'] = True
警告:BUNDLE_ERRORS是一個全局設置,它將覆蓋每一個RequestParser實例中的bundle_errors選項值。
每一個字段的錯誤消息均可以經過在Argument(也包括RequestParser.add_argument)中使用help參數來自定義。
若是沒有提供help參數,那麼該字段的錯誤消息將會是類型錯誤自己的字符串表示。若是提供了help參數,那麼錯誤消息將會是help參數的值。
help可能包含一個插入的符號{error_msg},它將會替換成類型錯誤的字符串表示。這種方式可以實現自定義錯誤消息,同時保留原始的錯誤消息。以下所示:
from flask_restplus import reqparse parser = reqparse.RequestParser() parser.add_argument( 'foo', choices=('one', 'two'), help='Bad choice: {error_msg}' ) # 若是請求中的'foo'參數值爲'three',那麼錯誤信息將會以下所示: { "message": { "foo": "Bad choice: three is not a valid choice", } }