Flask 使用URL 處理器

2021-08-11 09:51 更新

0.7 新版功能.

Flask 0.7 版引入了 URL 處理器的概念。此概念的意義在于,對(duì)于一部分資源, 您并不是很清楚該如何設(shè)定其 URL 相同的部分。例如可能有一些 URL 包含了幾個(gè)字母 來(lái)指定的多國(guó)語(yǔ)言語(yǔ)種,但是你不想在每個(gè)函數(shù)里都手動(dòng)識(shí)別到底是哪個(gè)語(yǔ)言。

搭配 Blueprint 使用時(shí),URL 處理器尤其有用。這里我們將會(huì)就具體的應(yīng)用例子介紹如何使用 URL 處理器和 Blueprint

國(guó)際化的應(yīng)用程序 URL

試想如下一個(gè)網(wǎng)頁(yè)應(yīng)用:

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
    ...

這可能會(huì)產(chǎn)生一大片重復(fù)的代碼,因?yàn)槟惚仨氃诿總€(gè)函數(shù)當(dāng)中手動(dòng)處理 g 對(duì)象。 當(dāng)然,你可以使用裝飾器來(lái)簡(jiǎn)化它,但想要從一個(gè)函數(shù)動(dòng)態(tài)生成 URL 到另一個(gè)函數(shù), 仍需詳細(xì)地提供這段多國(guó)語(yǔ)言代號(hào)碼,這將非常地惱人。

對(duì)于后者,這就是 url_defaults() 函數(shù)大展神威的地方了! 這些函數(shù)可以自動(dòng)地將值注入到 url_for() 的調(diào)用中去。下面的 代碼檢查多語(yǔ)言代號(hào)碼是否在包含各個(gè) URL 值的字典里,以及末端調(diào)用的函數(shù)是否接受 '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 映射的函數(shù) is_endpoint_expecting() 可以被用來(lái) 識(shí)別是否可以給末端的函數(shù)提供一個(gè)多國(guó)語(yǔ)言代號(hào)碼。

相反的函數(shù)是 url_value_preprocessor() 。他們?cè)谡?qǐng)求成功 匹配并且能夠執(zhí)行針對(duì) URL 值的代碼時(shí)立即執(zhí)行。實(shí)際上,他們將信息從包含這些值的 字典當(dāng)中取出,然后將其放在某個(gè)其他的地方:

@app.url_value_preprocessor
def pull_lang_code(endpoint, values):
    g.lang_code = values.pop('lang_code', None)

這樣,您再也不必在每個(gè)函數(shù)中都要將 lang_code 分配給 g 了。 您可以進(jìn)一步的改進(jìn)它,通過(guò)編寫您自己的裝飾器,并使用這些裝飾器為包含多國(guó)語(yǔ)言 代號(hào)碼的 URL 添加前綴。但是使用藍(lán)圖相比起來(lái)會(huì)更優(yōu)雅一些。一旦 'lang_code' 被從字典里彈出,他就不會(huì)在被傳遞到視圖函數(shù)當(dāng)中。這樣,代碼就可簡(jiǎn)化為如下形式:

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():
    ...

多國(guó)語(yǔ)言化的 Blueprint URL

因?yàn)?Blueprint 能夠自動(dòng)地為所有 URL 添加一個(gè)相同的字符串作為前綴,所以自動(dòng)處理這些函數(shù)變得非常簡(jiǎn)單。 每個(gè)藍(lán)圖都可以有一個(gè) URL 處理器,即從 url_defaults() 函數(shù)中 移除一整套業(yè)務(wù)邏輯,因?yàn)樗辉贆z查URL 是否真正與 'lang_code' 相關(guān):

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():
    ...


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)