Для обмена данными, допустимыми только для одного запроса, от одной функции к другой, глобальная переменная Python недостаточно хороша, т.к. в многопоточных средах может возникнуть условия гонки за эту переменную. Фреймворк Flask предоставляет специальный объект пространства имен flask.g
, который может хранить данные в контексте приложения.
Глобальный объект пространства имен flask.g
гарантирует, что он действителен только для активного запроса и будет возвращать разные значения для каждого запроса. В двух словах: flask.g
предназначен для передачи значений переменных от одной функции к другой в рамках одного запроса к сайту. Он делает ожидаемые вещи, как и для запроса и сессии/сеанса.
На самом деле, объект пространства имен flask.g
, представляет собой прокси объект для класса app.app_ctx_globals_class
экземпляра приложения, который по умолчанию имеет значение flask.ctx._AppCtxGlobals
.
В общем это хорошее место для хранения ресурсов во время запроса конкретного запроса. Очень распространенным шаблоном является хранение информации об авторизации пользователя и подключениях к базе данных в контексте приложения или в объекте flask.g
. Общий шаблон для этого состоит в том, чтобы поместить объект туда в начале запроса, а затем удалить его в конце запроса. Представьте, например, этот код, чтобы получить текущего пользователя:
def get_user(): user = getattr(g, 'user', None) if user is None: user = fetch_current_user_from_database() g.user = user return user
Внутри шаблонов приложения Flask, также есть доступ к глобальному объекту flask.g
flask.ctx._AppCtxGlobals
.Класс flask.ctx._AppCtxGlobals
- это простой объект. Предназначен для использования в качестве пространства имен для хранения данных в контексте приложения.
Создание контекста приложения, автоматически создает этот объект, который, в свою очередь, становится доступным в качестве глобального прокси-объекта flask.g
.
flask.ctx._AppCtxGlobals
.Так, как глобальный объект flask.g
- это прокси для flask.ctx._AppCtxGlobals
, то следовательно он так же поддерживает все описанные ниже операции.
'key' in g
: проверяет, присутствует ли атрибут 'key' в глобальном объекте flask.g
.iter(g)
: возвращает итератор по именам атрибутов глобального объекта flask.g
.g.get(name, default=None)
: получает атрибут по имени name
или если name
отсутствует возвращает значение по умолчанию default
. Другими словами, ведет себя подобно dict.get()
.g.pop(name, default=<object object>)
: возвращает, а потом удаляет атрибут по имени name
или если name
отсутствует возвращает значение по умолчанию default
. Другими словами, ведет себя подобно dict.pop()
.g.setdefault(name, default=None)
: получает значение атрибута name
, если оно присутствует, если отсутствует, то устанавливает атрибут name
и возвращает значение по умолчанию default
. Другими словами, ведет себя подобно dict.setdefault()
.flask.g
.Простой пример того, как можно хранить подключение к базе данных в глобальном объекте flask.g
в рамках одного запроса, на примере использования базы данных SQLite 3 в приложении Flask:
import sqlite3 from flask import g # расположение файла БД SQLite 3 DATABASE = '/path/to/database.db' def get_db(): """ Возвращает объект соединения с БД""" db = getattr(g, '_database', None) if db is None: db = g._database = sqlite3.connect(DATABASE) return db @app.teardown_appcontext def close_connection(exception): """Закрывает соединение с с БД""" db = getattr(g, '_database', None) if db is not None: db.close()
А затем использовать get_db()
в функциях-представлениях.
@app.route('/') def index(): cur = get_db().cursor() ...