.. _app-context: Контекст приложения Flask ========================= .. versionadded:: 0.9 Одно из проектных решений Flask заключается в том, что есть два разных “состояния”, в которых выполняется код. Состояние настройки приложения, которое подразумевается на уровне модуля. Оно наступает в момент, когда создаётся экземпляр объекта :class:`Flask`, и заканчивается, когда поступает первый запрос. Пока приложение находится в этом состоянии, верно следующее: - программист может безопасно менять объект приложения. - запросы ещё не обрабатывались. - у вас имеется ссылка на объект приложения, чтобы изменить его, нет необходимости пользоваться каким-либо посредником для того, чтобы получить ссылку на созданный или изменяемый объект приложения. Напротив, во время обработки запроса верны следующие правила: - пока активен запрос, объекты локального контекста (:data:`flask.request` и другие) указывают на текущий запрос. - любой код может в любое время может заполучить эти объекты. Есть и третье состояние, которое располагается между ними. Иногда можно работать с приложением так же, как и во время обработки запроса, просто в этот момент нет активного запроса. Например, вы можете работать с интерактивной оболочкой Python и взаимодействовать с приложением или запустить приложение из командной строки. Контекст приложения - это то, чем управляет локальный контекст :data:`~flask.current_app`. Назначение контекста приложения ------------------------------- Основная причина существования контекста приложений состоит в том, что в прошлом большая доля функциональности была привязана к контексту запроса за неимением лучшего решения. Тогда одной из целей, учитываемых при проектировании Flask, было обеспечение возможности иметь несколько приложений в рамках одного процесса Python. Каким образом код находит “правильное” приложение? В прошлом мы рекомендовали явную передачу приложений, но появились проблемы с библиотеками, которые не были спроектированы с учётом этого. Обходной путь решения этой проблемы заключался в том, чтобы использовать посредника :data:`~flask.current_app`, привязанного ссылкой к текущему запросу приложения. Но поскольку создание такого контекста запроса является не оправданно дорогостоящим в случае отсутствия запроса, был введён контекст приложения. Создание контекста приложения ----------------------------- Для создания контекста приложения есть два способа. Первый из них - неявный: когда поступает контекст запроса, при необходимости также создаётся и контекст приложения. В результате вы можете игнорировать существование контекста приложения до тех пор, пока он вам не понадобится. Второй способ - это явное создание контекста при помощи метода :meth:`~flask.Flask.app_context`:: from flask import Flask, current_app app = Flask(__name__) with app.app_context(): # within this block, current_app points to app. print current_app.name Контекст приложения также используется функцией :func:`~flask.url_for` в случае, если было настроено значение параметра конфигурации ``SERVER_NAME``. Это позволяет вам генерировать URL'ы даже при отсутствии запроса. Локальность контекста --------------------- Контекст приложения создаётся и уничтожается при необходимости. Он никогда не перемещается между потоками и не является общим для разных запросов. Поэтому - это идеальное место для хранения информации о подключении к базе данных и т.п. Внутренний объект стека называется :data:`flask._app_ctx_stack`. Расширения могут хранить дополнительную информацию на самом верхнем уровне, если предполагается, что они выбрали достаточно уникальное имя и если они помещают свою информацию сюда, а не в объект :data:`flask.g`, который зарезервирован для пользовательского кода. За дополнительной информацией по теме обратитесь к разделу :ref:`extension-dev`. Использование контекста ----------------------- Обычно контекст используют для кэширования в нём ресурсов, которые необходимо создавать в случае отдельных запросов или для постоянного использования. Например, соединения к базе данных предназначены для хранения именно там. Для сохранения чего-либо в контексте приложения необходимо выбирать уникальные имена, так как это то место, которое является общим для приложений и расширений Flask. Наиболее распространённым использованием является разделение управления ресурсами на две части: 1. неявное кэширование ресурсов в контексте. 2. освобождение ресурса, основанное на демонтировании контекста. В обычном случае, должна присутствовать функция ``get_X()``, которая создаёт ресурс ``X``, если он ещё не существует, и, если это не так, возвращает тот же самый ресурс, а также функция ``teardown_X()``, которая регистрирует обработчик демонтирования. Вот пример соединения с базой данных:: import sqlite3 from flask import g def get_db(): db = getattr(g, '_database', None) if db is None: db = g._database = connect_to_database() return db @app.teardown_appcontext def teardown_db(exception): db = getattr(g, '_database', None) if db is not None: db.close() Соединение будет установлено, когда ``get_db()`` вызывается в первый раз. Для того, чтобы сделать это неявно, можно использовать класс :class:`~werkzeug.local.LocalProxy`:: from werkzeug.local import LocalProxy db = LocalProxy(get_db) С использованием этого способа пользователь может иметь прямой доступ к ``db``, которая сама внутри себя вызовет ``get_db()``. `Оригинал этой страницы `_