Использование обработчиков URL
Журнал изменений
Новое в версии 0.7.
Flask 0.7 вводит понятие обработчиков URL. Идея в том, что у вас может быть множество ресурсов с общими частями в URL, которые вы не всегда явно хотите предоставлять. Например, у вас может быть множество URL, содержащих код языка, но вы не хотите обрабатывать его в каждой функции самостоятельно.
Обработчики URL особенно полезны при использовании с blueprints. Здесь мы рассмотрим обработчики URL, специфичные как для приложения, так и для blueprints.
Международные 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
Метод is_endpoint_expecting() карты URL можно использовать для определения, имеет ли смысл передавать код языка для данной конечной точки.
Обратной стороной этих функций являются обработчики 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, но более изящное решение – использовать blueprint. После того, как '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 Blueprint
Поскольку blueprints могут автоматически добавлять общий префикс ко всем URL, легко автоматически добавлять его ко всем функциям. Кроме того, blueprints могут иметь обработчики URL, специфичные для blueprint, что значительно упрощает логику функции 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():
...
© 2007–2022 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/2.2.x/patterns/urlprocessors/