Контекст приложения
Контекст приложения отслеживает данные приложения на уровне приложения во время запроса, выполнения команды CLI или другой активности. Вместо передачи приложения каждой функции, вместо этого используются прокси current_app и g.
Это аналогично Контексту запроса, который отслеживает данные запроса во время запроса. Соответствующий контекст приложения помещается при помещении контекста запроса.
Назначение контекста
Объект приложения Flask имеет атрибуты, такие как config, которые полезны для доступа в представлениях и командах CLI. Однако импорт экземпляра app в модули вашего проекта подвержен проблемам циклических импортов. При использовании паттерна фабрики приложения или написании переиспользуемых blueprints или расширений экземпляра app для импорта может и не быть.
Flask решает эту проблему с помощью контекста приложения. Вместо того, чтобы ссылаться на app напрямую, используйте прокси current_app, который указывает на приложение, обрабатывающее текущую активность.
Flask автоматически помещает контекст приложения при обработке запроса. Функции представлений, обработчики ошибок и другие функции, выполняющиеся во время запроса, получат доступ к current_app.
Flask также автоматически поместит контекст приложения при запуске команд CLI, зарегистрированных с помощью Flask.cli, используя @app.cli.command().
Срок жизни контекста
Контекст приложения создается и уничтожается по мере необходимости. Когда приложение Flask начинает обрабатывать запрос, оно помещает контекст приложения и контекст запроса. Когда запрос завершается, извлекается контекст запроса, а затем контекст приложения. Как правило, контекст приложения будет иметь такой же срок жизни, как и запрос.
См. Контекст запроса для получения дополнительной информации о том, как работают контексты и весь жизненный цикл запроса.
Вручную поместить контекст
Если вы попытаетесь получить доступ к current_app или чему-либо, что использует его, вне контекста приложения, вы получите это сообщение об ошибке:
RuntimeError: Working outside of application context. This typically means that you attempted to use functionality that needed to interface with the current application object in some way. To solve this, set up an application context with app.app_context().
Если вы видите эту ошибку при настройке приложения, например, при инициализации расширения, вы можете вручную поместить контекст, поскольку у вас есть прямой доступ к app. Используйте app_context() в with блоке, и все, что выполняется в этом блоке, получит доступ к current_app.
def create_app():
app = Flask(__name__)
with app.app_context():
init_db()
return app
Если вы видите эту ошибку где-то еще в вашем коде, не связанном с настройкой приложения, это, скорее всего, означает, что вы должны перенести этот код в функцию представления или команду CLI.
Хранение данных
Контекст приложения — хорошее место для хранения общих данных во время запроса или выполнения команды CLI. Flask предоставляет g object для этой цели. Это простой объект пространства имен, который имеет такой же срок жизни, как и контекст приложения.
Примечание
Имя g обозначает «глобальный», но это относится к данным, являющимся глобальными в пределах контекста. Данные на g теряются после завершения контекста, и это неподходящее место для хранения данных между запросами. Используйте session или базу данных для хранения данных между запросами.
Частое использование g — управление ресурсами во время запроса.
-
get_X()создаёт ресурсX, если он не существует, кешируя его какg.X. -
teardown_X()закрывает или иным образом освобождает ресурс, если он существует. Он зарегистрирован как обработчикteardown_appcontext().
Например, вы можете управлять соединением с базой данных с помощью этого шаблона:
from flask import g
def get_db():
if 'db' not in g:
g.db = connect_to_database()
return g.db
@app.teardown_appcontext
def teardown_db():
db = g.pop('db', None)
if db is not None:
db.close()
Во время запроса каждый вызов get_db() вернёт одно и то же соединение, и оно будет автоматически закрыто в конце запроса.
Вы можете использовать LocalProxy для создания нового контекстного локального объекта из get_db():
from werkzeug.local import LocalProxy db = LocalProxy(get_db)
Обращение к db вызовет get_db внутри, таким же образом, как работает current_app.
Если вы пишете расширение, g следует зарезервировать для кода пользователя. Вы можете хранить внутренние данные в самом контексте, но обязательно используйте достаточно уникальное имя. Текущий контекст доступен с помощью _app_ctx_stack.top. Дополнительная информация см. в Разработка расширений Flask.
События и сигналы
Приложение вызовет функции, зарегистрированные с помощью teardown_appcontext(), когда контекст приложения будет удалён.
Если signals_available имеет значение «истина», следующие сигналы отправляются: appcontext_pushed, appcontext_tearing_down и appcontext_popped.
© 2007–2020 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/1.0.x/appcontext/