當前位置:成語大全網 - 新華字典 - 如何自定義Flask中的響應類

如何自定義Flask中的響應類

大部分應用並不直接使用Flask中的響應類(Response class),但這並不是說這個類沒有用武之地;實際上,Flask會為每個請求創建響應對象。那麽,它是如何實現的呢?

Flask用來處理請求的函數返回時,響應周期就開始了。在網絡應用中,路由通常最後會調用render_template函數,渲染引用的模板文件,將其作為字符串返回:

@app.route('/index')

def index():

# ...

return render_template('index.html')

但是,妳可能也知道,Flask的路由函數可以選擇額外返回兩個值,這兩個值將被分別設為HTTP狀態碼和自定義的HTTP響應標頭:

@app.route('/data')

def index():

# ...

return render_template('data.json'), 201, {'Content-Type': 'application/json'}

在上面的例子中,狀態碼被設為201,取代了Flask默認的200,即請求被成功處理的狀態碼。這個例子還定義了內容類型標頭(Content-Type header),表明HTTP響應中包含JSON數據,因為如果妳不明確設置內容類型的話,Flask會默認設置為HTML。

上面的例子介紹了HTTP響應的三個基本組成部分,即數據或正文、狀態碼和標頭。Flask的應用實例擁有壹個make_response函數,可以接受路由函數的返回值(可以是單個值,也可以是有1-3個值的元組),並將其填入響應對象(Response object)中。

妳可以通過Python控制臺會話(console session),看看整個過程。首先創建壹個虛擬環境,並安裝Flask,然後開啟Python會話,並輸入下面的代碼:

>>> from flask import Flask

>>> app = Flask(__name__)

>>> app.make_response('Hello, World')

<Response 12 bytes [200 OK]>

>>> app.make_response(('Hello, World', 201))

<Response 12 bytes [201 CREATED]>

這裏,我創建了壹個簡單的Flask應用實例,之後調用了make_response()方法創建響應類對象。第壹次調用時,我傳了壹個字符串作為參數,所以響應對象中使用了默認的狀態碼和標頭。第二次調用時,我傳入了有兩個值的元組,強制返回了非默認的狀態碼。註意,第二次調用時使用了兩個括號,裏層的括號將字符串和狀態碼包在了元組中。由於make_response()函數只接受壹個參數,所以必須要這樣做。

Flask在創建了代表路由函數返回值的響應對象(Response object)之後,還會做壹些處理。包括將響應對象傳入自定義的after_request處理程序(handlers),在這壹步,應用還有有機會插入或修改標頭、更改正文或狀態碼,如果願意的話,甚至是啟用嶄新的的響應對象取而代之。最後,Flask會獲取最終的響應對象,渲染成HTTP響應,並發送給客戶端。

Flask中的響應類

我們來看看響應類中最有趣的特性。下面的類定義,展示了我眼中這個類所具備的靈活屬性和方法:

class Response:

charset = 'utf-8'

default_status = 200

default_mimetype = 'text/html'

def __init__(self, response=None, status=None, headers=None,

mimetype=None, content_type=None, direct_passthrough=False):

pass

@classmethod

def force_type(cls, response, environ=None):

pass

註意,如果妳去翻閱Flask的源碼,是找不到上述類定義的。Flask中的Response類,實際上衍生自Werkzeug庫中的壹個同名類。而Werzeug中的Response類繼承的是BaseResponse類,這個類中就包含了上述定義。

charset、default_status和default_mimetype這三個類屬性定義了相應的默認值。如果任何壹個默認值不適用妳的應用,那麽妳可以創建Response類的子類,定義妳自己的默認值,而不必在每壹個響應對象中設置自定義值。例如,如果妳的應用是壹個所有的路由均返回XML格式數據的API接口,妳就可以在自定義的類中,將default_mimetype改為application/xml,這樣Flask就會默認返回XML響應。稍後妳會看到如何實現。

這裏,我不會詳細介紹__init__構造函數(妳可以閱讀Werkzeug的文檔),但請註意,Flask響應對象中的三個重要元素,即響應正文、狀態碼和標頭,是作為參數傳入的。在子類中,構造函數可以改變創建響應的相應規則。

響應類中的force_type()類方法,是唯壹比較復雜,但又很重要的元素。有時候,Werkzeug或是Flask需要自行創建響應對象,比如出現應用錯誤,並需要將其返回給客戶端時。在這種情況下,響應對象不是應用提供的,而是由框架創建的。在使用自定義響應類的應用中,Flask和Werkzeug無法知道自定義類的細節,所以它們使用標準響應類來創建響應。響應類中的force_type()方法,被設計為可以接受不同響應類的實例,並會將其轉換成自身的格式。

我敢肯定,妳壹定被force_type()方法的描述搞糊塗了。說白了,就是如果Flask碰到了壹個不是其期望的響應對象,就會使用該方法進行轉換。我下面要講的第三個使用場景,就利用了這個特點,讓Flask的路由函數返回諸如字典、列表或者是其他任何自定義對象,作為請求的響應對象。

好了,理論就講這麽多了。接下來,我來告訴大家如何應用上面有關響應類的小技巧。準備好了嗎?

使用自定義的響應類

到現在為止,我確定妳也會認為:在部分有趣的場景下,使用自定義的響應類是有利的。在給出實際例子之前,我想告訴妳在Flask中設置並使用自定義的響應類是多麽的簡單。請看下面的這個例子:

from flask import Flask, Response

class MyResponse(Response):

pass

app = Flask(__name__)

app.response_class = MyResponse

# ...

在上面的代碼中,我定義了壹個名叫MyResponse的自定義響應類。通常,自定義響應類會增加或修改默認類的行為,所以壹般都會通過創建Flask中Response類的子類來實現。要想讓Flask使用自定義類,我只需要設置app.response_class即可。

Flask類中的response_class是壹個類屬性,所以我們可以稍微修改上面的例子,創建壹個設置了自定義響應類的Flask子類:

from flask import Flask, Response

class MyResponse(Response):

pass

class MyFlask(Flask)

response_class = MyResponse

app = MyFlask(__name__)

# ...