Flask может генерировать URL с помощью функции url_for()
из пакета flask
. URL можно задавать вручную в шаблонах и функциях представления, но это не очень хорошая практика. Предположим, возникла необходимость поменять структуру ссылок для блога с /<id>/<post-title>/
на /<id>/post/<post-title>/
. Если URL были заданы вручную в шаблонах и функциях, тогда придется вручную редактировать их во всех местах. Функция url_for()
позволяет произвести то же изменение одним щелчком.
Функция url_for()
принимает конечную точку и возвращает URL в виде строки. Стоит напомнить, что конечная точка ссылается на уникальное имя URL и в большинстве случае — это имя функции представления. Например, сейчас main2.py
имеет определенный корневой путь(/
):
#...
@app.route('/')
def index():
return render_template('index.html', name='Jerry')
#...
Чтобы сгенерировать корневой URL, нужно вызвать url_for()
следующим образом: url_for(‘index’)
. Выводом будет '/'
. Следующий код демонстрирует, как использовать url_for()
в консоли.
>>> from main2 import app
>>> from flask import url_for
>>>
>>> with app.test_request_context('/api'): # путь /api выбран произвольно
... url_for('index')
...
'/'
>>>
Стоит обратить внимание, что сперва создается контекст запроса (и таким образом — контекст приложения). Если попробовать использовать url_for()
внутри консоли без вызова контекста, выйдет ошибка. Больше о контекстах запросов и приложения можно прочитать здесь.
Если url_for()
не может создать URL, она вызовет исключение BuildError
.
>>>
>>> with app.test_request_context('/api'):
... url_for('/api')
...
Traceback (most recent call last):
...
werkzeug.routing.BuildError: Could not build url for endpoint '/api
Did you mean 'static' instead?
>>>
Чтобы сгенерировать абсолютной URL, нужно передать функции url_for()
аргумент external=True
:
>>>
>>> with app.test_request_context('/api'):
... url_for('index', _external=True)
...
'https://localhost:5000/'
>>>
Вместо того чтобы прописывать URL в функции redirect()
, стоит всегда использовать url_for()
для этого. Например:
@app.route('/admin/')
def admin():
if not loggedin:
return redirect(url_for('login')) # если не залогинен, выполнять редирект на страницу входа
return render_template('admin.html')
Чтобы сгенерировать URL для динамических адресов, нужно передать динамические части в виде аргументов-ключевых слов. Например:
>>>
>>> with app.test_request_context('/api'):
... url_for('user_profile', user_id = 100)
...
'/user/100/'
>>>
>>>
>>> with app.test_request_context('/api'):
... url_for('books', genre='biography')
...
'/books/biography/'
>>>
Дополнительные аргументы-ключевые слова, переданные функции url_for()
, будут добавлены к URL в виде строки запроса.
>>>
>>> with app.test_request_context('/api'):
... url_for('books', genre='biography', page=2, sort_by='date-published')
...
'/books/biography/?page=2&sort_by=date-published'
>>>
url_for()
— одна из тех функций, которую можно использовать внутри шаблона. Чтобы сгенерировать URL внутри шаблонов, нужно просто вызвать url_for()
внутри фигурных скобок {{ … }}:
<a href="{{ url_for('books', genre='biography') }}">Books</a>
Вывод:
<a href="/books/biography/">Books</a>