Сообщить об ошибке.

Функция url_for() модуля flask в Python

Автоматическое создание URL-адреса для функции-представления во Flask

Синтаксис:

import flask

flask.url_for(endpoint, **values)

Параметры:

  • endpoint - конечная точка URL (имя функции-представления),
  • **values - переменные аргументы правила URL-адреса.
  • _external - если установлено значение True, то создается абсолютный URL. Адрес сервера можно изменить с помощью переменной конфигурации SERVER_NAME, которая возвращается к заголовку Host, а затем к IP и порту запроса.
  • _scheme - строка, определяющая желаемую URL-схему. При этом аргумент _external должен иметь значение True, в противном случае возникает ошибка ValueError. Поведение по умолчанию использует ту же схему, что и текущий запрос, или если контекст запроса недоступен, то PREFERRED_URL_SCHEME. Может быть установлен в пустую строку '' для построения URL-адресов, относящихся к протоколу.
  • _anchor - если предусмотрено, то добавляется в качестве привязки к URL-адресу.
  • _method - если предусмотрено, то явно указывает HTTP-метод.

Возвращаемое значение:

  • строка с URL-адресом или исключение BuildError.

Описание:

Функция url_for() создает URL-адрес для заданной конечной точки endpoint (функции-представления).

Ключевые аргументы **values, которые неизвестны целевой конечной точке endpoint (функции-представления), добавляются к сгенерированному URL-адресу в качестве параметров запроса как '?name=val&name1=val1'. Если значение параметра запроса является None (foo=None), то вся пара пропускается.

Если flask.url_for() генерирует URL-адрес для схемы blueprint, то для одной и той же схемы можно сокращать ссылки, добавив к локальной конечной точке endpoint префикс точки .. Например выражение url_for('.index') будет ссылаться на функцию index(), локальную для текущего blueprint.

Значения конфигурации APPLICATION_ROOT и SERVER_NAME используются только при генерации URL-адресов вне контекста запроса.

Для интеграции приложений во Flask, есть перехватчик ошибок построения URL через Flask.url_build_error_handlers. Функция url_for() приводит к ошибке BuildError, когда текущее приложение не имеет URL-адреса для данной конечной точки endpoint и значений **values. Когда это происходит, то flask.current_app() вызывает свои app.url_build_error_handlers, если он не равен None, который может возвращать строку для использования в качестве результата url_for() (вместо url_for() по умолчанию, вызывает исключение BuildError) или повторно вызывать исключение. Пример:

def external_url_handler(error, endpoint, values):
    "Ищет внешний URL-адрес, когда url_for не может создать URL-адрес."
    # Пример подключения `build_error_handler`.
    # Здесь `lookup_url` - это созданная служебная функция, 
    # которая ищет конечную точку во внешнем реестре URL-адресов.
    url = lookup_url(endpoint, **values)
    if url is None:
        # Внешний поиск URL-адреса не дал результатов.
        # Повторно вызываем `BuildError` в контексте исходной трассировки.
        exc_type, exc_value, tb = sys.exc_info()
        if exc_value is error:
            raise exc_type(exc_value).with_traceback(tb)
        else:
            raise error
    # `url_for()` будет использовать этот результат вместо исключения `BuildError`
    return url

# подключение функции `external_url_handler`
app.url_build_error_handlers.append(external_url_handler)

Например, error - это экземпляр BuildError, а конечная точка endpoint и значения values - это аргументы, переданные в url_for(). Обратите внимание, что код предназначен для создания URL-адресов вне текущего приложения, а не для обработки ошибок 404 NotFound.

Пример генерации URL-адреса для функции-представления.

Что бы автоматически создать URL-адрес для функций-представлений, декорированных @app.route(), необходимо использовать url_for(). В качестве первого аргумента она принимает имя функции-представления и любое количество ключевых аргументов, каждый из которых соответствует изменяемой части URL-адреса (например, в URL '/user/<username>' - изменяемая часть username). Если указываются ключевые аргументы, которые отсутствует в изменяемых частях URL-адреса, то все они добавляются к URL в качестве параметров запроса (например, ?next=then).

>>> from flask import Flask, url_for
>>> app = Flask(__name__)
>>> @app.route('/')
... def index(): pass
... 
>>> @app.route('/login')
... def login(): pass
... 
>>> @app.route('/user/<username>')
... def profile(username): pass
... 
>>> with app.test_request_context():
...     print(url_for('index'))
...     print(url_for('login'))
...     # переменной `next` нет в маршруте `/login`
...     print(url_for('login', next='then'))
...     print(url_for('profile', username='admin'))
... 
# /
# /login
# /login?next=then
# /user/admin

В примере использован метод app.test_request_context(), который заставляет Flask вести себя так, как будто он обрабатывает запрос, даже при взаимодействии с ним через интерпретатор Python.

Пример создание ссылки на URL-адрес в шаблоне jinja2.

Для создания ссылки на URL-адрес в шаблоне jinja2 необходимо сделать что-то подобное:

<a href="{{ url_for('get_post', year=year, month=month, title=title)}}">
    {{ title }}
</a>

Если URL-адрес содержит много ключевых аргументов и url_for() желательно использовать с распаковкой ключевых аргументов, в стиле:

{{ url_for('get_post', **post) }}

То необходимо изменить код на что-то вроде этого:

@route('/posts/')
def get_all_posts():
    # допустим, что используется модель БД
    models = database_posts
    posts = []
    for model in models:
        posts.append(dict(year=model.year, month=model.month, title=model.title))
    return render_template('posts.html', posts=posts)

Тогда код шаблона может выглядеть как-то так:

{% for post in posts %}
    <a href="{{ url_for('get_post', **post) }}">
        {{ post['title'] }}
    </a>
{% endfor %}

На этом этапе можно создать метод для модели, что-бы каждый раз в коде не нужно было превращать его в словарь.

Для обработки статических файлов настоятельно рекомендуется использовать диспетчер активов, такой как Flask-Assets, чтобы обслуживать статику с помощью Flask, смотрите материал "Как обслуживать статические файлы в Flask Python".