• en
  • Language: ru
  • Documentation version: 1.1.x

Использование процессоров URL

Добавлено в версии 0.7.

Flask 0.7 вводит концепцию процессоров URL. Идея заключается в том, что у вас может быть куча ресурсов с общими частями в URL, которые вы не всегда хотите предоставлять явно. Например, у вас может быть куча URL, в которых есть код языка, но вы не хотите обрабатывать его в каждой функции самостоятельно.

URL-процессоры особенно полезны в сочетании с чертежами. Здесь мы рассмотрим как URL-процессоры для конкретных приложений, так и специфические для blueprint’ов.

Интернационализированные 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()s. Они выполняются сразу после того, как запрос был согласован, и могут выполнять код, основанный на значениях 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-адреса Blueprint

Поскольку blueprints может автоматически префиксировать все URL общей строкой, это легко сделать автоматически для каждой функции. Кроме того, в blueprint’ах могут быть процессоры 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():
    ...