使用 URL 處理器¶
變更日誌
在版本 0.7 中新增。
Flask 0.7 引入了 URL 處理器的概念。這個想法是,您可能有一堆資源,它們的 URL 中有共同的部分,但您不總是想明確地提供這些部分。例如,您可能有一堆 URL 包含語言代碼,但您不想在每個函數中都處理它。
當與藍圖結合使用時,URL 處理器特別有用。我們將在這裡處理應用程式特定的 URL 處理器以及藍圖的細節。
國際化的應用程式 URL¶
考慮像這樣的應用程式
from flask import Flask, g
app = Flask(__name__)
@app.route('/<lang_code>/')
def index(lang_code):
g.lang_code = lang_code
...
@app.route('/<lang_code>/about')
def about(lang_code):
g.lang_code = lang_code
...
這是一個非常多的重複,因為您必須在每個函數中自行處理 g
物件上的語言代碼設定。當然,可以使用裝飾器來簡化此操作,但是如果您想從一個函數生成 URL 到另一個函數,您仍然需要顯式提供語言代碼,這可能會很煩人。
對於後者,這就是 url_defaults()
函數的用武之地。它們可以自動將值注入到 url_for()
的呼叫中。下面的程式碼檢查語言代碼是否尚未在 URL 值的字典中,以及端點是否需要名為 'lang_code'
的值
@app.url_defaults
def add_language_code(endpoint, values):
if 'lang_code' in values or not g.lang_code:
return
if app.url_map.is_endpoint_expecting(endpoint, 'lang_code'):
values['lang_code'] = g.lang_code
URL 映射的方法 is_endpoint_expecting()
可以用來判斷為給定的端點提供語言代碼是否有意義。
該函數的反向是 url_value_preprocessor()
。它們在請求匹配後立即執行,並且可以根據 URL 值執行程式碼。這個想法是它們從值字典中提取資訊並將其放在其他地方
@app.url_value_preprocessor
def pull_lang_code(endpoint, values):
g.lang_code = values.pop('lang_code', None)
這樣您就不再需要在每個函數中將 lang_code
賦值給 g
。您可以通過編寫自己的裝飾器來改進這一點,該裝飾器以語言代碼作為 URL 的前綴,但更優雅的解決方案是使用藍圖。一旦 'lang_code'
從值字典中彈出,它將不再轉發到視圖函數,從而將程式碼簡化為這樣
from flask import Flask, g
app = Flask(__name__)
@app.url_defaults
def add_language_code(endpoint, values):
if 'lang_code' in values or not g.lang_code:
return
if app.url_map.is_endpoint_expecting(endpoint, 'lang_code'):
values['lang_code'] = g.lang_code
@app.url_value_preprocessor
def pull_lang_code(endpoint, values):
g.lang_code = values.pop('lang_code', None)
@app.route('/<lang_code>/')
def index():
...
@app.route('/<lang_code>/about')
def about():
...
國際化的藍圖 URL¶
因為藍圖可以自動為所有 URL 添加一個通用字串作為前綴,所以很容易自動為每個函數執行此操作。此外,藍圖可以具有每個藍圖的 URL 處理器,這從 url_defaults()
函數中移除了很多邏輯,因為它不再需要檢查 URL 是否真的對 'lang_code'
參數感興趣
from flask import Blueprint, g
bp = Blueprint('frontend', __name__, url_prefix='/<lang_code>')
@bp.url_defaults
def add_language_code(endpoint, values):
values.setdefault('lang_code', g.lang_code)
@bp.url_value_preprocessor
def pull_lang_code(endpoint, values):
g.lang_code = values.pop('lang_code')
@bp.route('/')
def index():
...
@bp.route('/about')
def about():
...