Контекст приложения

Контекст приложения отслеживает данные уровня приложения во время запроса, команды CLI или другого действия. Вместо того чтобы передавать приложение каждой функции, вместо этого осуществляется доступ к прокси current_app и g.

Это аналогично Контекст запроса, который отслеживает данные уровня запроса во время запроса. Соответствующий контекст приложения выталкивается, когда выталкивается контекст запроса.

Назначение контекста

Объект приложения Flask имеет атрибуты, такие как config, к которым полезно обращаться в представлениях и CLI commands. Однако импортирование экземпляра app в модули вашего проекта чревато проблемами циклического импорта. При использовании app factory pattern или написании повторно используемых blueprints или extensions вообще не будет экземпляра app для импорта.

Flask решает эту проблему с помощью контекста приложения. Вместо того чтобы напрямую обращаться к app, вы используете прокси current_app, который указывает на приложение, обрабатывающее текущую активность.

Flask автоматически pushes контекст приложения при обработке запроса. Функции представления, обработчики ошибок и другие функции, выполняемые во время запроса, будут иметь доступ к current_app.

Flask также будет автоматически передавать контекст приложения при выполнении команд CLI, зарегистрированных в Flask.cli, используя @app.cli.command().

Срок службы контекста

Контекст приложения создается и уничтожается по мере необходимости. Когда приложение Flask начинает обрабатывать запрос, оно выталкивает контекст приложения и request context. Когда запрос заканчивается, он выталкивает контекст запроса, а затем контекст приложения. Как правило, контекст приложения имеет такое же время жизни, как и запрос.

Более подробную информацию о том, как работают контексты и полный жизненный цикл запроса, смотрите в Контекст запроса.

Ручное перемещение контекста

Если вы попытаетесь получить доступ к 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 используется для управления ресурсами во время запроса.

  1. get_X() создает ресурс X, если он не существует, кэшируя его как g.X.

  2. 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(exception):
    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.

События и сигналы

Приложение будет вызывать функции, зарегистрированные в teardown_appcontext(), когда контекст приложения будет раскрыт.

Если signals_available истинно, посылаются следующие сигналы: appcontext_pushed, appcontext_tearing_down и appcontext_popped.

Вернуться на верх