Структура и жизненный цикл приложения
Flask упрощает создание веб-приложений. Но приложение и каждый обрабатываемый им запрос состоят из нескольких компонентов. Знание того, что происходит при настройке приложения, обработке запросов и их обслуживании, поможет вам понять возможности Flask и структурировать своё приложение.
Настройка приложения
Первый шаг в создании приложения Flask — создание объекта приложения. Каждое приложение Flask — это экземпляр класса Flask, который собирает всю конфигурацию, расширения и представления.
from flask import Flask
app = Flask(__name__)
app.config.from_mapping(
SECRET_KEY="dev",
)
app.config.from_prefixed_env()
@app.route("/")
def index():
return "Hello, World!"
Это известно как «фаза настройки приложения», это код, который вы пишете вне функций представлений или других обработчиков. Его можно разбить на разные модули и подпакеты, но весь код, который вы хотите включить в своё приложение, должен быть импортирован, чтобы его можно было зарегистрировать.
Все настройки приложения должны быть завершены до начала обслуживания приложения и обработки запросов. Это связано с тем, что WSGI-серверы распределяют работу между несколькими рабочими процессами или могут быть распределены по нескольким машинам. Если конфигурация изменится в одном рабочем процессе, Flask не может гарантировать согласованность между другими рабочими процессами.
Flask старается помочь разработчикам обнаружить некоторые из этих проблем с порядком настройки, отображая ошибку, если методы, связанные с настройкой, вызываются после обработки запросов. В этом случае вы увидите следующую ошибку:
Метод настройки ‘route’ больше не может быть вызван для приложения. Оно уже обработало свой первый запрос, любые изменения не будут применены согласованно. Убедитесь, что все импорты, декораторы, функции и т. д., необходимые для настройки приложения, выполнены до запуска.
Однако Flask не может обнаружить все случаи неверной последовательности настройки. В целом, не изменяйте объект приложения Flask и объекты Blueprint из функций представлений, которые выполняются во время обработки запросов. Это включает:
- Добавление маршрутов, функций представлений и других обработчиков запросов с
@app.route,@app.errorhandler,@app.before_request, и т.д. - Регистрация blue-prints.
- Загрузку конфигурации с помощью
app.config. - Настройку среды шаблонов Jinja с помощью
app.jinja_env. - Установку интерфейса сеансов вместо стандартных cookie itsdangerous.
- Установку поставщика JSON с
app.json, вместо стандартного поставщика. - Создание и инициализацию расширений Flask.
Обслуживание приложения
Flask — это фреймворк WSGI. Другая половина WSGI — это WSGI-сервер. Во время разработки Flask, через Werkzeug, предоставляет сервер WSGI для разработки с помощью команды flask run в командной строке. Когда вы закончите разработку, используйте сервер для производства, см. Развёртывание в производственной среде.
Независимо от используемого сервера, он будет следовать спецификации WSGI PEP 3333. WSGI-серверу будет сообщено, как получить доступ к объекту вашего приложения Flask, который является WSGI-приложением. Затем он начнёт прослушивать HTTP-запросы, преобразовывать данные запроса в WSGI environ и вызывать WSGI-приложение с этими данными. WSGI-приложение вернёт данные, которые будут преобразованы в HTTP-ответ.
- Браузер или другой клиент отправляет HTTP-запрос.
- WSGI-сервер получает запрос.
- WSGI-сервер преобразует данные HTTP в WSGI
environсловарь. - WSGI-сервер вызывает WSGI-приложение с
environ. - Flask, как WSGI-приложение, выполняет всю внутреннюю обработку, чтобы направить запрос к функции представления, обработать ошибки и т. д.
- Flask преобразует возвращаемое значение функции представления в данные WSGI-ответа, передаёт их WSGI-серверу.
- WSGI-сервер создаёт и отправляет HTTP-ответ.
- Клиент получает HTTP-ответ.
Средство-посредник
WSGI-приложение выше — это вызываемый объект, который ведет себя определенным образом. Средство-посредник — это WSGI-приложение, которое обертывает другое WSGI-приложение. Это аналогичный принцип Python-декораторам. Внешнее средство-посредник вызывается сервером. Оно может изменять передаваемые ему данные, затем вызывать WSGI-приложение (или дальнейшее средство-посредник), которое оно обертывает, и так далее. И оно может взять возвращаемое значение этого вызова и дополнительно изменить его.
С точки зрения WSGI-сервера существует одно WSGI-приложение, которое он вызывает напрямую. Как правило, Flask является «действительным» приложением в конце цепочки средств-посредников. Но даже Flask может вызывать дальнейшие WSGI-приложения, хотя это продвинутый и нечастый случай использования.
Распространённым средством-посредником, используемым с Flask, является ProxyFix Werkzeug, который изменяет запрос так, чтобы он выглядел как поступающий напрямую от клиента, даже если он прошёл через HTTP-прокси. Существуют и другие средства-посредники, которые могут обрабатывать предоставление статических файлов, аутентификацию и т.д.
Как обрабатывается запрос
Для нас интересной частью вышеперечисленных шагов является момент, когда Flask вызывается сервером WSGI (или middleware). В этот момент Flask выполняет множество операций для обработки запроса и создания ответа. В самом простом случае он сопоставляет URL с функцией представления, вызывает функцию представления и возвращает её результат обратно серверу. Но есть и множество других способов настройки его поведения.
- Сервер WSGI вызывает объект Flask, который, в свою очередь, вызывает
Flask.wsgi_app(). - Создаётся объект
RequestContext. Этот объект преобразует словарь WSGIenvironв объектRequest. Он также создаёт объектAppContext. - Контекст приложения (app context) помещается в стек, что делает доступными
current_appиg. - Отправляется сигнал
appcontext_pushed. - Контекст запроса (request context) помещается в стек, что делает доступными
requestиsession. - Сессия открывается, загружая любые существующие данные сессии с использованием интерфейса сессии приложения
session_interface, экземпляраSessionInterface. - URL сопоставляется с правилами URL, зарегистрированными с помощью декоратора
route()во время настройки приложения. Если соответствия нет, ошибка (обычно 404, 405 или переадресация) сохраняется для обработки позже. - Отправляется сигнал
request_started. - Вызываются функции, декорированные
url_value_preprocessor(). - Вызываются функции, декорированные
before_request(). Если какая-либо из этих функций возвращает значение, оно сразу же обрабатывается как ответ. - Если URL не сопоставился с маршрутом на предыдущих шагах, эта ошибка возбуждается сейчас.
- Вызывается функция представления, декорированная
route(), связанная с сопоставленным URL, и возвращает значение, используемое в качестве ответа. - Если на каком-либо шаге произошла ошибка, и существует функция, декорированная
errorhandler(), которая соответствует классу исключения или коду HTTP-ошибки, она вызывается для обработки ошибки и возврата ответа. - Любое значение, вернувшее ответ — функция before request, функция представления или обработчик ошибок — преобразуется в объект
Response. - Вызываются функции, декорированные
after_this_request(), затем очищаются. - Вызываются функции, декорированные
after_request(), которые могут изменить объект ответа. - Сессия сохраняется, сохраняя любые изменённые данные сессии с использованием интерфейса сессии приложения
session_interface. - Отправляется сигнал
request_finished. - Если на каком-либо шаге произошла ошибка, и она не была обработана функцией обработчика ошибок, она обрабатывается сейчас. HTTP-исключения обрабатываются как ответы с соответствующим кодом состояния, другие исключения преобразуются в универсальный ответ 500. Отправляется сигнал
got_request_exception. - Статус, заголовки и тело объекта ответа возвращаются серверу WSGI.
- Вызываются функции, декорированные
teardown_request(). - Отправляется сигнал
request_tearing_down. - Контекст запроса удаляется из стека,
requestиsessionбольше недоступны. - Вызываются функции, декорированные
teardown_appcontext(). - Отправляется сигнал
appcontext_tearing_down. - Контекст приложения удаляется из стека,
current_appиgбольше недоступны. - Отправляется сигнал
appcontext_popped.
Существует ещё больше декораторов и точек настройки, чем это, но они не входят в цикл жизни каждого запроса. Они более специфичны для определённых действий, которые вы можете использовать во время запроса, таких как шаблоны, построение URL или обработка данных JSON. Смотрите остальную часть документации, а также API для дальнейшего изучения.
© 2007–2022 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/2.3.x/lifecycle/