Spec-Zone.ru › Flask 0.12

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

Журнал изменений

Новая версия 0.9.

Одна из идей дизайна Flask заключается в том, что существуют два разных «состояния», в которых выполняется код. Состояние настройки приложения, в котором приложение неявно находится на уровне модуля. Оно начинается, когда создаётся объект Flask, и неявно завершается, когда поступает первый запрос. Пока приложение находится в этом состоянии, выполняются несколько предположений:

  • программист может безопасно изменить объект приложения.
  • обработка запросов ещё не происходила
  • для изменения приложения необходимо иметь ссылку на объект приложения, нет магического прокси, который может предоставить ссылку на объект приложения, который вы в данный момент создаёте или изменяете.

В отличие от этого, во время обработки запроса существуют несколько других правил:

  • в то время, как запрос активен, локальные объекты контекста (flask.request и другие) указывают на текущий запрос.
  • любой код может получить доступ к этим объектам в любое время.

Существует третье состояние, которое находится между ними. Иногда вы взаимодействуете с приложением таким образом, как и во время обработки запросов, только активного запроса нет. Например, вы работаете в интерактивной оболочке Python и взаимодействуете с приложением или в приложении командной строки.

Контекст приложения обеспечивает контекстный локальный объект current_app.

Назначение контекста приложения

Основная причина существования контекста приложения заключается в том, что в прошлом множество функций было прикреплено к контексту запроса из-за отсутствия лучшего решения. Поскольку одна из основ дизайна Flask заключается в том, что в одном процессе Python может быть более одного приложения.

Итак, как код находит «правильное» приложение? В прошлом мы рекомендовали явно передавать приложения, но это создавало проблемы с библиотеками, которые не были разработаны с этим в виду.

Распространённым обходным путём для решения этой проблемы было использование прокси current_app позже, который связывался со ссылкой на приложение текущего запроса. Поскольку создание такого контекста запроса является излишне дорогостоящей операцией в случае отсутствия запроса, был введён контекст приложения.

Создание контекста приложения

Существует два способа создания контекста приложения. Первый — неявный: всякий раз, когда контекст запроса добавляется, контекст приложения будет создан вместе с ним, если это необходимо. В результате вы можете игнорировать существование контекста приложения, если вам это не нужно.

Второй способ — явный, с помощью метода 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

Контекст приложения также используется функцией url_for() в случае, если был сконфигурирован SERVER_NAME. Это позволяет генерировать URL даже при отсутствии запроса.

Если контекст запроса не был добавлен, и контекст приложения не был явно задан, будет поднято исключение RuntimeError.

RuntimeError: Working outside of application context.

Локальность контекста

Контекст приложения создаётся и уничтожается по мере необходимости. Он никогда не перемещается между потоками и не будет общим для запросов. Таким образом, он идеально подходит для хранения информации о подключении к базе данных и других данных. Внутренний объект стека называется flask._app_ctx_stack. Расширения могут свободно хранить дополнительную информацию на верхнем уровне, если они выбирают достаточно уникальное имя и должны поместить туда свою информацию вместо объекта flask.g, который зарезервирован для пользовательского кода.

Дополнительную информацию можно найти в Разработка расширений Flask.

Использование контекста

Контекст обычно используется для кэширования ресурсов, которые необходимо создавать для каждого запроса или случая использования. Например, соединения с базой данных предназначены для этого. При хранении чего-либо в контексте приложения следует выбирать уникальные имена, так как это место, где совместно работают приложения 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(), будет установлено соединение. Чтобы сделать это неявным, можно использовать LocalProxy:

from werkzeug.local import LocalProxy
db = LocalProxy(get_db)

Таким образом, пользователь может напрямую получить доступ к db, которая внутри вызывает get_db().

© 2007–2020 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/0.12.x/appcontext/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API