使用 URL 处理器¶
更新日志
在 0.7 版本中添加。
Flask 0.7 引入了 URL 处理器的概念。 其想法是,您可能有一堆资源,它们的 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():
...