Структура и жизненный цикл приложения
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, и т.д. - Регистрация blueprints.
- Загрузка конфигурации с помощью
app.config. - Настройка среды шаблонов Jinja с помощью
app.jinja_env. - Настройка интерфейса сессий вместо стандартных cookie itsdangerous.
- Установка поставщика JSON с помощью
app.json, вместо стандартного поставщика. - Создание и инициализация расширений Flask.
Обслуживание приложения
Flask — это фреймворк приложений WSGI. Другая половина WSGI — это сервер WSGI. Во время разработки Flask, через Werkzeug, предоставляет сервер WSGI разработки с помощью команды flask run CLI. После завершения разработки используйте сервер производства для обслуживания вашего приложения, см. Развертывание в продакшен.
Независимо от используемого сервера, он будет следовать спецификации 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 выше — это вызываемый объект, который ведет себя определённым образом. Middleware — это приложение WSGI, которое оборачивает другое приложение WSGI. Это похожая концепция, как Python-декораторы. Наружный middleware вызывается сервером. Он может изменять передаваемые данные, затем вызывать приложение WSGI (или дальнейший middleware), которое оно оборачивает, и так далее. И он может взять возвращаемое значение этого вызова и дополнительно изменить его.
С точки зрения сервера WSGI, существует одно приложение WSGI, то, которое он вызывает напрямую. Как правило, Flask является «настоящим» приложением в конце цепочки middleware. Но даже Flask может вызывать дальнейшие приложения WSGI, хотя это продвинутый, редкий случай.
Распространённое средство, используемое с Flask, — это ProxyFix Werkzeug, который изменяет запрос так, чтобы он выглядел так, как будто он пришёл напрямую от клиента, даже если он прошёл через HTTP-прокси по пути. Есть и другие средства, которые могут обрабатывать предоставление статических файлов, аутентификацию и т.д.
Как обрабатывается запрос
Для нас интересной частью вышеприведённых шагов является момент, когда сервер WSGI (или middleware) вызывает Flask. В этот момент Flask выполняет значительный объём работы по обработке запроса и генерации ответа. В самом простом случае это сопоставление URL с функцией-вью, вызов этой функции-вью и передача возвращаемого значения обратно серверу. Но есть и множество других аспектов, которые можно использовать для настройки его поведения.
- Сервер WSGI вызывает объект Flask, который вызывает
Flask.wsgi_app(). - Создаётся объект
RequestContext. Этот объект преобразует словарь WSGIenvironв объектRequest. Также создаётся объектAppContext. - Контекст приложения контекст приложения подталкивается, что делает
current_appиgдоступными. - Отправляется сигнал
appcontext_pushed. - Подталкивается контекст запроса контекст запроса, что делает
requestиsessionдоступными. - Сессия открывается, загружая любые существующие данные сессии с использованием интерфейса сессии приложения
session_interface, экземпляраSessionInterface. - URL сопоставляется с правилами URL, зарегистрированными с помощью декоратора
route()во время настройки приложения. Если сопоставления нет, ошибка — обычно 404, 405 или перенаправление — сохраняется для обработки позже. - Отправляется сигнал
request_started. - Вызываются функции, декорированные
url_value_preprocessor(). - Вызываются функции, декорированные
before_request(). Если какая-либо из этих функций возвращает значение, оно сразу обрабатывается как ответ. - Если URL не был сопоставлен с маршрутом на нескольких шагах назад, эта ошибка теперь поднимается.
- Вызывается функция-вью, декорированная
route()и связанная с сопоставленным URL, которая возвращает значение, используемое в качестве ответа. - Если на каком-либо шаге произошла ошибка, и существует функция, декорированная
errorhandler(), которая соответствует классу исключения или коду HTTP-ошибки, она вызывается для обработки ошибки и возврата ответа. - То, что вернуло значение ответа — функция до запроса, вью или обработчик ошибок — это значение преобразуется в объект
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, чтобы углубиться в изучение.
© 2010 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/stable/lifecycle/