Контекстные/поточно-локальные сеансы

Помните, в разделе Когда я строю Session, когда фиксирую его и когда закрываю? было введено понятие «области действия сеанса» с акцентом на веб-приложения и практику связывания области действия Session с областью действия веб-запроса. Большинство современных веб-фреймворков включают инструменты интеграции, позволяющие автоматически управлять областью видимости Session, и эти инструменты следует использовать по мере их появления.

SQLAlchemy включает собственный объект-помощник, который помогает в создании определяемых пользователем диапазонов Session. Он также используется сторонними интеграционными системами для построения своих интеграционных схем.

Объект является объектом scoped_session и представляет собой реестр объектов Session. Если вы не знакомы с шаблоном реестра, хорошее введение можно найти в Patterns of Enterprise Architecture.

Предупреждение

Реестр scoped_session по умолчанию использует Python threading.local() для отслеживания экземпляров Session. Это не обязательно совместимо со всеми серверами приложений, особенно с теми, которые используют greenlets или другие альтернативные формы контроля параллелизма, что может привести к условиям гонки (например, случайно возникающим сбоям) при использовании в сценариях с умеренным или высоким параллелизмом. Пожалуйста, прочитайте Нить-локальный прицел и Использование Thread-Local Scope в веб-приложениях ниже для более полного понимания последствий использования threading.local() для отслеживания объектов Session и рассмотрите более явные средства определения масштаба при использовании серверов приложений, не основанных на традиционных потоках.

Примечание

Объект scoped_session является очень популярным и полезным объектом, используемым многими приложениями SQLAlchemy. Однако важно отметить, что он представляет только один подход к вопросу управления Session. Если вы новичок в SQLAlchemy, и особенно если термин «потоково-локальная переменная» кажется вам странным, мы рекомендуем вам по возможности сначала ознакомиться с готовой системой интеграции, такой как Flask-SQLAlchemy или zope.sqlalchemy.

A scoped_session is constructed by calling it, passing it a factory which can create new Session objects. A factory is just something that produces a new object when called, and in the case of Session, the most common factory is the sessionmaker, introduced earlier in this section. Below we illustrate this usage:

>>> from sqlalchemy.orm import scoped_session
>>> from sqlalchemy.orm import sessionmaker

>>> session_factory = sessionmaker(bind=some_engine)
>>> Session = scoped_session(session_factory)

Созданный нами объект scoped_session теперь будет обращаться к sessionmaker при «вызове» реестра:

>>> some_session = Session()

Выше, some_session является экземпляром Session, который мы теперь можем использовать для общения с базой данных. Этот же Session присутствует и в созданном нами реестре scoped_session. Если мы обратимся к реестру во второй раз, то получим в ответ тот же Session:

>>> some_other_session = Session()
>>> some_session is some_other_session
True

Этот шаблон позволяет разным частям приложения обращаться к глобальному scoped_session, так что все эти части могут использовать одну и ту же сессию без необходимости передавать ее в явном виде. Session, который мы создали в нашем реестре, будет оставаться до тех пор, пока мы явно не скажем нашему реестру утилизировать его, вызвав scoped_session.remove():

>>> Session.remove()

Метод scoped_session.remove() сначала вызывает Session.close() на текущем Session, что имеет эффект освобождения любых соединений/транзакционных ресурсов, принадлежащих Session, а затем отбрасывает сам Session. «Освобождение» здесь означает, что соединения возвращаются в свой пул соединений, а все транзакционные состояния откатываются назад, в конечном счете, с использованием метода rollback() основного соединения DBAPI.

В этот момент объект scoped_session является «пустым» и при повторном вызове создаст новый Session. Как показано ниже, это уже не тот Session, который мы имели раньше:

>>> new_session = Session()
>>> new_session is some_session
False

Приведенная выше серия шагов в двух словах иллюстрирует идею шаблона «реестр». Имея на руках эту основную идею, мы можем обсудить некоторые детали работы этого шаблона.

Неявный доступ к методу

Задача scoped_session проста: хранить Session для всех, кто его запрашивает. В качестве средства более прозрачного доступа к этому Session, scoped_session также включает прокси-поведение, что означает, что с самим реестром можно обращаться как с Session непосредственно; когда методы вызываются на этом объекте, они проксируются на базовый Session, поддерживаемый реестром:

Session = scoped_session(some_factory)

# equivalent to:
#
# session = Session()
# print(session.scalars(select(MyClass)).all())
#
print(Session.scalars(select(MyClass)).all())

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

Нить-локальный прицел

Пользователи, знакомые с многопоточным программированием, заметят, что представление чего-либо в виде глобальной переменной обычно является плохой идеей, поскольку это подразумевает, что доступ к глобальному объекту будет осуществляться одновременно во многих потоках. Объект Session полностью предназначен для использования неконкурентным способом, что в терминах многопоточного программирования означает «только в одном потоке за раз». Поэтому наш вышеприведенный пример использования scoped_session, когда один и тот же объект Session поддерживается в нескольких вызовах, предполагает, что необходимо предусмотреть некоторый процесс, чтобы несколько вызовов во многих потоках не получали доступа к одной и той же сессии. Мы называем это понятие поточное локальное хранилище, что означает, что используется специальный объект, который будет поддерживать отдельный объект для каждого потока приложения. Python предоставляет такую возможность с помощью конструкции threading.local(). Объект scoped_session по умолчанию использует этот объект в качестве хранилища, так что для всех, кто обращается к реестру scoped_session, сохраняется один объект Session, но только в рамках одного потока. Абоненты, обращающиеся к реестру в другом потоке, получают экземпляр Session, который является локальным для этого другого потока.

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

Метод scoped_session.remove(), как всегда, удаляет текущий Session, связанный с потоком, если таковой имеется. Однако одним из преимуществ объекта threading.local() является то, что если поток приложения завершается, то «хранилище» для этого потока также собирается в мусор. Таким образом, фактически «безопасно» использовать локальную область видимости потока в приложении, которое порождает и уничтожает потоки, без необходимости вызывать scoped_session.remove(). Однако область видимости самих транзакций, т.е. их завершение с помощью Session.commit() или Session.rollback(), обычно остается чем-то, что должно быть явно организовано в соответствующее время, если только приложение не связывает время жизни потока с временем жизни транзакции.

Использование Thread-Local Scope в веб-приложениях

Как обсуждалось в разделе Когда я строю Session, когда фиксирую его и когда закрываю?, веб-приложение строится вокруг концепции веб-запроса, и интеграция такого приложения с Session обычно подразумевает, что Session будет связан с этим запросом. Как оказалось, большинство веб-фреймворков Python, за заметными исключениями, такими как асинхронные фреймворки Twisted и Tornado, используют потоки простым способом, таким образом, что конкретный веб-запрос принимается, обрабатывается и завершается в рамках одного рабочего потока. Когда запрос завершается, рабочий поток передается в пул рабочих, где он может быть доступен для обработки другого запроса.

Это простое соответствие веб-запроса и потока означает, что ассоциирование Session с потоком подразумевает, что он также ассоциируется с веб-запросом, выполняемым в этом потоке, и наоборот, при условии, что Session создается только после начала веб-запроса и уничтожается непосредственно перед его завершением. Поэтому обычной практикой является использование scoped_session в качестве быстрого способа интеграции Session с веб-приложением. Приведенная ниже диаграмма последовательности иллюстрирует этот поток:

Web Server          Web Framework        SQLAlchemy ORM Code
--------------      --------------       ------------------------------
startup        ->   Web framework        # Session registry is established
                    initializes          Session = scoped_session(sessionmaker())

incoming
web request    ->   web request     ->   # The registry is *optionally*
                    starts               # called upon explicitly to create
                                         # a Session local to the thread and/or request
                                         Session()

                                         # the Session registry can otherwise
                                         # be used at any time, creating the
                                         # request-local Session() if not present,
                                         # or returning the existing one
                                         Session.execute(select(MyClass)) # ...

                                         Session.add(some_object) # ...

                                         # if data was modified, commit the
                                         # transaction
                                         Session.commit()

                    web request ends  -> # the registry is instructed to
                                         # remove the Session
                                         Session.remove()

                    sends output      <-
outgoing web    <-
response

Используя вышеприведенный поток, процесс интеграции Session с веб-приложением имеет ровно два требования:

  1. Создайте единственный реестр scoped_session при первом запуске веб-приложения, гарантируя, что этот объект будет доступен остальной части приложения.

  2. Убедитесь, что scoped_session.remove() вызывается при завершении веб-запроса, обычно это делается путем интеграции с системой событий веб-фреймворка для создания события «on request end».

Как отмечалось ранее, вышеприведенный шаблон является только одним из возможных способов интеграции Session с веб-фреймворком, который, в частности, делает существенное допущение, что веб-фреймворк ассоциирует веб-запросы с потоками приложения. Однако настоятельно рекомендуется использовать вместо :class:`.scoped_session` инструменты интеграции, поставляемые с самим веб-фреймворком, если таковые имеются.

В частности, хотя использование локального потока может быть удобным, предпочтительно, чтобы Session был связан непосредственно с запросом, а не с текущим потоком. В следующем разделе о пользовательских диапазонах подробно описана более продвинутая конфигурация, которая может сочетать использование scoped_session с прямым диапазоном, основанным на запросе, или с любым другим видом диапазона.

Использование созданных пользователем областей видимости

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

Предположим, что веб-фреймворк определяет библиотечную функцию get_current_request(). Приложение, построенное с использованием этого фреймворка, может вызвать эту функцию в любое время, и результатом будет некий объект Request, представляющий текущий обрабатываемый запрос. Если объект Request является хэшируемым, то эта функция может быть легко интегрирована с scoped_session, чтобы связать Session с запросом. Ниже мы проиллюстрируем это в сочетании с гипотетическим маркером событий, предоставляемым веб-фреймворком on_request_end, который позволяет вызывать код всякий раз, когда запрос заканчивается:

from my_web_framework import get_current_request, on_request_end
from sqlalchemy.orm import scoped_session, sessionmaker

Session = scoped_session(sessionmaker(bind=some_engine), scopefunc=get_current_request)


@on_request_end
def remove_session(req):
    Session.remove()

Выше мы инстанцируем scoped_session обычным образом, за исключением того, что мы передаем нашу функцию возврата запроса в качестве «scopefunc». Это инструктирует scoped_session использовать эту функцию для генерации ключа словаря всякий раз, когда реестр вызывается для возврата текущего Session. В этом случае особенно важно, чтобы была реализована надежная система «удаления», поскольку этот словарь не является самоуправляемым.

API контекстной сессии

Object Name Description

QueryPropertyDescriptor

Описывает тип, применяемый к атрибуту уровня класса scoped_session.query_property().

scoped_session

Обеспечивает масштабируемое управление объектами Session.

ScopedRegistry

Реестр, который может хранить один или несколько экземпляров одного класса на основе функции «scope».

ThreadLocalRegistry

ScopedRegistry, который использует переменную threading.local() для хранения.

class sqlalchemy.orm.scoped_session

Обеспечивает масштабируемое управление объектами Session.

Смотрите учебник Контекстные/поточно-локальные сеансы.

Примечание

При использовании Асинхронный ввод/вывод (asyncio) вместо scoped_session следует использовать асинхронно-совместимый класс async_scoped_session.

Классная подпись

класс sqlalchemy.orm.scoped_session (typing.Generic)

method sqlalchemy.orm.scoped_session.__call__(**kw: Any) _S

Возвращает текущий Session, создавая его с помощью scoped_session.session_factory, если он отсутствует.

Параметры:

**kw – Аргументы ключевых слов будут переданы в вызываемый модуль scoped_session.session_factory, если нет существующего Session. Если Session присутствует и были переданы аргументы ключевых слов, то будет вызвана команда InvalidRequestError.

method sqlalchemy.orm.scoped_session.__init__(session_factory: sessionmaker[_S], scopefunc: Optional[Callable[[], Any]] = None)

Создайте новый scoped_session.

Параметры:
  • session_factory – фабрика для создания новых экземпляров Session. Обычно, но не обязательно, это экземпляр sessionmaker.

  • scopefunc – необязательная функция, определяющая текущую область видимости. Если функция не передана, объект scoped_session принимает «потоково-локальную» область видимости и будет использовать Python threading.local() для сохранения текущего Session. Если функция передана, она должна вернуть хэшируемый токен; этот токен будет использоваться как ключ в словаре для хранения и извлечения текущего Session.

method sqlalchemy.orm.scoped_session.add(instance: object, _warn: bool = True) None

Поместите объект в этот Session.

Выступает от имени класса Session от имени класса scoped_session.

Объекты, находящиеся в состоянии transient при передаче в метод Session.add(), перейдут в состояние pending до следующей промывки, после которой они перейдут в состояние persistent.

Объекты, которые находятся в состоянии detached при передаче в метод Session.add(), перейдут в состояние persistent напрямую.

Если транзакция, используемая Session, откатывается, объекты, которые были переходными, когда они были переданы в Session.add(), будут переведены обратно в состояние transient и больше не будут присутствовать в этом Session.

method sqlalchemy.orm.scoped_session.add_all(instances: Iterable[object]) None

Добавляет заданную коллекцию экземпляров к данному Session.

Выступает от имени класса Session от имени класса scoped_session.

Общее описание поведения см. в документации для Session.add().

attribute sqlalchemy.orm.scoped_session.autoflush

Прокси для атрибута Session.autoflush от имени класса scoped_session.

method sqlalchemy.orm.scoped_session.begin(nested: bool = False) SessionTransaction

Начать транзакцию или вложенную транзакцию на этом Session, если она еще не начата.

Выступает от имени класса Session от имени класса scoped_session.

Объект Session имеет поведение autobegin, поэтому обычно нет необходимости в явном вызове метода Session.begin(). Однако он может быть использован для того, чтобы контролировать область действия, когда начинается транзакционное состояние.

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

Параметры:

nested – если True, начинает транзакцию SAVEPOINT и эквивалентна вызову Session.begin_nested(). Документацию по транзакциям SAVEPOINT смотрите в разделе Использование SAVEPOINT.

Результат:

объект SessionTransaction. Обратите внимание, что SessionTransaction действует как менеджер контекста Python, позволяя использовать Session.begin() в блоке «with». Смотрите пример Явное начало.

method sqlalchemy.orm.scoped_session.begin_nested() SessionTransaction

Начните «вложенную» транзакцию на этой сессии, например, SAVEPOINT.

Выступает от имени класса Session от имени класса scoped_session.

Для правильной работы этого метода целевая база данных (базы данных) и соответствующие драйверы должны поддерживать SQL SAVEPOINT.

Документацию по транзакциям SAVEPOINT см. в разделе Использование SAVEPOINT.

Результат:

объект SessionTransaction. Обратите внимание, что SessionTransaction действует как менеджер контекста, позволяя использовать Session.begin_nested() в блоке «with». Пример использования см. в Использование SAVEPOINT.

См.также

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

Сериализуемая изоляция / Точки сохранения / Транзакционный DDL - специальные обходные пути, необходимые для работы драйвера SQLite, чтобы SAVEPOINT работал правильно.

attribute sqlalchemy.orm.scoped_session.bind

Прокси для атрибута Session.bind от имени класса scoped_session.

method sqlalchemy.orm.scoped_session.bulk_insert_mappings(mapper: Mapper[Any], mappings: Iterable[Dict[str, Any]], return_defaults: bool = False, render_nulls: bool = False) None

Выполните массовую вставку заданного списка картографических словарей.

Выступает от имени класса Session от имени класса scoped_session.

Legacy Feature

Этот метод является унаследованной функцией, начиная с версии 2.0 серии SQLAlchemy. О современных массовых INSERT и UPDATE см. разделы ORM Bulk INSERT Statements и ORM Bulk UPDATE по первичному ключу. API версии 2.0 разделяет детали реализации с этим методом и добавляет новые возможности.

Параметры:
  • mapper – сопоставленный класс, или реальный объект Mapper, представляющий единственный вид объекта, представленный в списке сопоставления.

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

  • return_defaults – при значении True процесс INSERT будет изменен таким образом, чтобы обеспечить получение вновь созданных значений первичного ключа. Этот параметр обычно используется для того, чтобы обеспечить массовую вставку сопоставлений Joined Table Inheritance. … Примечание:: для бэкендов, не поддерживающих RETURNING, параметр Session.bulk_insert_mappings.return_defaults может значительно снизить производительность, поскольку операторы INSERT больше не могут быть объединены в пакет. Смотрите Поведение «Вставка многих значений» для операторов INSERT для получения информации о том, какие бэкенды затронуты.

  • render_nulls – Если значение None равно True, то в оператор INSERT будет включено значение NULL, а не столбец будет опущен в INSERT. Это позволяет всем вводимым строкам иметь одинаковый набор столбцов, что позволяет передавать полный набор строк в DBAPI. Обычно каждый набор столбцов, содержащий другую комбинацию значений NULL, чем предыдущий ряд, должен опускать другую серию столбцов из оператора INSERT, что означает, что он должен быть выдан как отдельный оператор. Передача этого флага гарантирует, что весь набор строк можно объединить в один пакет; однако ценой этого является то, что серверные настройки по умолчанию, которые вызываются опущенным столбцом, будут пропущены, поэтому следует позаботиться о том, чтобы в них не было необходимости. … предупреждение:: Когда этот флаг установлен, значения SQL по умолчанию на стороне сервера не будут вызываться для тех столбцов, которые вставлены как NULL; значение NULL будет отправлено явно. Необходимо позаботиться о том, чтобы для операции в целом не требовалось вызывать серверные функции по умолчанию.

method sqlalchemy.orm.scoped_session.bulk_save_objects(objects: Iterable[object], return_defaults: bool = False, update_changed_only: bool = True, preserve_order: bool = True) None

Выполните массовое сохранение заданного списка объектов.

Выступает от имени класса Session от имени класса scoped_session.

Legacy Feature

Этот метод является унаследованной функцией, начиная с версии 2.0 серии SQLAlchemy. О современных массовых INSERT и UPDATE см. разделы ORM Bulk INSERT Statements и ORM Bulk UPDATE по первичному ключу.

Для общего INSERT и UPDATE существующих объектов, отображаемых ORM, предпочитайте стандартные паттерны управления данными unit of work, представленные в Унифицированный учебник по SQLAlchemy в Манипулирование данными с помощью ORM. SQLAlchemy 2.0 теперь использует Поведение «Вставка многих значений» для операторов INSERT с современными диалектами, что решает предыдущие проблемы медлительности массового INSERT.

Параметры:
  • objects – последовательность сопоставленных экземпляров объектов. Сопоставленные объекты сохраняются как есть и не ассоциируются с Session впоследствии. Для каждого объекта, будет ли он отправлен как INSERT или UPDATE, зависит от тех же правил, которые используются Session в традиционной операции; если у объекта установлен атрибут InstanceState.key, то предполагается, что объект «отсоединен» и в результате будет UPDATE. В противном случае используется INSERT. В случае UPDATE утверждения группируются на основе того, какие атрибуты изменились, и, следовательно, должны быть предметом каждого предложения SET. Если update_changed_only имеет значение False, то все атрибуты, присутствующие в каждом объекте, применяются к оператору UPDATE, что может помочь в группировке операторов в более крупный executemany(), а также уменьшит накладные расходы на проверку истории атрибутов.

  • return_defaults – при значении True строки, в которых отсутствуют значения, генерирующие значения по умолчанию, а именно целочисленные первичные ключи по умолчанию и последовательности, будут вставляться по одному, чтобы значение первичного ключа было доступно. В частности, это позволит корректно вставлять объединенное наследование и другие многотабличные отображения без необходимости предоставлять значения первичного ключа заранее; однако Session.bulk_save_objects.return_defaults значительно снижает прирост производительности метода в целом. Настоятельно рекомендуется использовать стандартный подход Session.add_all().

  • update_changed_only – При значении True операторы UPDATE отображаются на основе тех атрибутов в каждом состоянии, которые зарегистрировали изменения. При значении False все присутствующие атрибуты отображаются в предложение SET, за исключением атрибутов первичного ключа.

  • preserve_order – когда True, порядок вставок и обновлений точно соответствует порядку, в котором заданы объекты. Когда False, общие типы объектов группируются по вставкам и обновлениям, чтобы обеспечить больше возможностей для пакетной обработки.

method sqlalchemy.orm.scoped_session.bulk_update_mappings(mapper: Mapper[Any], mappings: Iterable[Dict[str, Any]]) None

Выполните массовое обновление заданного списка картографических словарей.

Выступает от имени класса Session от имени класса scoped_session.

Legacy Feature

Этот метод является унаследованной функцией, начиная с версии 2.0 серии SQLAlchemy. О современных массовых INSERT и UPDATE см. разделы ORM Bulk INSERT Statements и ORM Bulk UPDATE по первичному ключу. API версии 2.0 разделяет детали реализации с этим методом и добавляет новые возможности.

Параметры:
  • mapper – сопоставленный класс, или реальный объект Mapper, представляющий единственный вид объекта, представленный в списке сопоставления.

  • mappings – последовательность словарей, каждый из которых содержит состояние сопоставленной строки, подлежащей обновлению, в терминах имен атрибутов сопоставленного класса. Если отображение относится к нескольким таблицам, например, отображение с объединенным наследованием, каждый словарь может содержать ключи, соответствующие всем таблицам. Все ключи, которые присутствуют и не являются частью первичного ключа, применяются к пункту SET оператора UPDATE; значения первичного ключа, которые требуются, применяются к пункту WHERE.

method sqlalchemy.orm.scoped_session.close() None

Закройте транзакционные ресурсы и объекты ORM, используемые этой Session.

Выступает от имени класса Session от имени класса scoped_session.

Это удаляет все объекты ORM, связанные с данным Session, завершает любую выполняющуюся транзакцию и releases любые Connection объекты, которые данный Session сам выписал из связанных Engine объектов. Операция оставляет Session в состоянии, в котором он может быть использован снова.

Совет

Метод Session.close() не препятствует повторному использованию сессии. Сам Session на самом деле не имеет отдельного состояния «закрыто»; это просто означает, что Session освободит все соединения с базой данных и объекты ORM.

Изменено в версии 1.4: Метод Session.close() не создает сразу новый объект SessionTransaction; вместо этого новый SessionTransaction создается только в том случае, если Session снова используется для операции с базой данных.

См.также

Закрытие - подробно о семантике Session.close()

classmethod sqlalchemy.orm.scoped_session.close_all() None

Закройте все сессии в памяти.

Выступает от имени класса Session от имени класса scoped_session.

Не рекомендуется, начиная с версии 1.3: Метод Session.close_all() является устаревшим и будет удален в одном из будущих выпусков. Пожалуйста, обратитесь к close_all_sessions().

method sqlalchemy.orm.scoped_session.commit() None

Очистка ожидающих изменений и фиксация текущей транзакции.

Выступает от имени класса Session от имени класса scoped_session.

Когда операция COMMIT завершена, все объекты полностью expired, стирается их внутреннее содержимое, которое будет автоматически загружено заново при следующем обращении к объектам. В промежуточный момент эти объекты находятся в просроченном состоянии и не будут функционировать, если к ним detached из Session. Кроме того, эта операция повторной загрузки не поддерживается при использовании асинхронно-ориентированных API. Параметр Session.expire_on_commit может быть использован для отключения этого поведения.

Если для Session не существует транзакции, указывающей на то, что с момента предыдущего вызова Session.commit() для этого Session не было вызвано никаких операций, метод начнет и зафиксирует только внутреннюю «логическую» транзакцию, которая обычно не влияет на базу данных, если только не были обнаружены ожидающие изменения флеша, но все равно вызовет обработчики событий и правила истечения срока действия объектов.

Внешняя транзакция базы данных фиксируется безусловно, автоматически освобождая все действующие SAVEPOINT.

method sqlalchemy.orm.scoped_session.configure(**kwargs: Any) None

переконфигурировать sessionmaker, используемый этим scoped_session.

См. sessionmaker.configure().

method sqlalchemy.orm.scoped_session.connection(bind_arguments: Optional[_BindArguments] = None, execution_options: Optional[_ExecuteOptions] = None) Connection

Возвращает объект Connection, соответствующий транзакционному состоянию этого объекта Session.

Выступает от имени класса Session от имени класса scoped_session.

Возвращается либо Connection, соответствующий текущей транзакции, либо, если транзакция не выполняется, начинается новая и возвращается Connection (обратите внимание, что транзакционное состояние не устанавливается с DBAPI до тех пор, пока не будет выдан первый SQL-оператор).

Неоднозначность в многосвязных или несвязанных объектах Session может быть разрешена с помощью любого из необязательных аргументов ключевого слова. В конечном итоге для разрешения используется метод get_bind().

Параметры:
  • bind_arguments – словарь аргументов связывания. Может включать «mapper», «bind», «clause», другие пользовательские аргументы, которые передаются в Session.get_bind().

  • execution_options – словарь параметров выполнения, которые будут переданы в Connection.execution_options(), только при первом получении соединения. Если соединение уже присутствует в Session, выдается предупреждение и аргументы игнорируются. … см. также:: Настройка уровней изоляции транзакций / DBAPI AUTOCOMMIT

method sqlalchemy.orm.scoped_session.delete(instance: object) None

Пометить экземпляр как удаленный.

Выступает от имени класса Session от имени класса scoped_session.

При передаче предполагается, что объект находится в состоянии persistent или detached; после вызова метода объект будет находиться в состоянии persistent до следующей процедуры flush. В течение этого времени объект также будет членом коллекции Session.deleted.

При следующей промывке объект перейдет в состояние deleted, указывающее на то, что для его строки в текущей транзакции был выпущен оператор DELETE. Когда транзакция успешно зафиксирована, удаленный объект переходит в состояние detached и больше не присутствует в этом Session.

attribute sqlalchemy.orm.scoped_session.deleted

Набор всех экземпляров, помеченных как «удаленные» в пределах данного Session.

Выступает от имени класса Session от имени класса scoped_session.

attribute sqlalchemy.orm.scoped_session.dirty

Множество всех постоянных экземпляров, которые считаются грязными.

Выступает от имени класса Session от имени класса scoped_session.

Например:

some_mapped_object in session.dirty

Экземпляры считаются грязными, если они были изменены, но не удалены.

Обратите внимание, что этот «грязный» расчет является «оптимистичным»; большинство операций по установке атрибутов или изменению коллекции пометит экземпляр как «грязный» и поместит его в этот набор, даже если нет чистого изменения значения атрибута. Во время промывки значение каждого атрибута сравнивается с его ранее сохраненным значением, и если чистого изменения нет, операция SQL не выполняется (это более дорогая операция, поэтому она выполняется только во время промывки).

Чтобы проверить, есть ли у экземпляра действующие чистые изменения атрибутов, используйте метод Session.is_modified().

method sqlalchemy.orm.scoped_session.execute(statement: Executable, params: Optional[_CoreAnyExecuteParams] = None, *, execution_options: OrmExecuteOptionsParameter = {}, bind_arguments: Optional[_BindArguments] = None, _parent_execute_state: Optional[Any] = None, _add_event: Optional[Any] = None) Result[Any]

Выполнение конструкции выражения SQL.

Выступает от имени класса Session от имени класса scoped_session.

Возвращает объект Result, представляющий результаты выполнения оператора.

Например:

from sqlalchemy import select
result = session.execute(
    select(User).where(User.id == 5)
)

API-контракт Session.execute() аналогичен контракту Connection.execute(), 2.0 style версии Connection.

Изменено в версии 1.4: метод Session.execute() теперь является основной точкой выполнения операторов ORM при использовании 2.0 style ORM.

Параметры:
  • statement – Исполняемый оператор (т.е. выражение Executable, например select()).

  • params – Необязательный словарь или список словарей, содержащих значения связанных параметров. Если словарь один, то происходит выполнение одной строки; если список словарей, то будет вызван «executemany». Ключи в каждом словаре должны соответствовать именам параметров, присутствующих в операторе.

  • execution_options – необязательный словарь опций выполнения, которые будут связаны с выполнением оператора. Этот словарь может предоставлять подмножество опций, которые принимаются Connection.execution_options(), а также может предоставлять дополнительные опции, понятные только в контексте ORM. … seealso:: Варианты выполнения ORM - специфические для ORM параметры выполнения

  • bind_arguments – словарь дополнительных аргументов для определения привязки. Может включать «mapper», «bind» или другие пользовательские аргументы. Содержимое этого словаря передается в метод Session.get_bind().

Результат:

объект Result.

method sqlalchemy.orm.scoped_session.expire(instance: object, attribute_names: Optional[Iterable[str]] = None) None

Истечение срока действия атрибутов экземпляра.

Выступает от имени класса Session от имени класса scoped_session.

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

Чтобы одновременно исключить все объекты в Session, используйте Session.expire_all().

Поведение объекта Session по умолчанию заключается в том, что при вызове методов Session.rollback() или Session.commit() все состояние истекает, так что новое состояние может быть загружено для новой транзакции. По этой причине вызов метода Session.expire() имеет смысл только в том случае, если в текущей транзакции был выдан нестандартный SQL-запрос.

Параметры:
  • instance – Экземпляр, который необходимо обновить.

  • attribute_names – необязательный список строковых имен атрибутов, указывающих на подмножество атрибутов, срок действия которых истекает.

method sqlalchemy.orm.scoped_session.expire_all() None

Истечение срока действия всех постоянных экземпляров в рамках этой сессии.

Выступает от имени класса Session от имени класса scoped_session.

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

Чтобы исключить отдельные объекты и отдельные атрибуты этих объектов, используйте Session.expire().

Поведение объекта Session по умолчанию заключается в том, что при вызове методов Session.rollback() или Session.commit() все состояние истекает, чтобы новое состояние могло быть загружено для новой транзакции. По этой причине вызов Session.expire_all() обычно не требуется, если транзакция изолирована.

method sqlalchemy.orm.scoped_session.expunge(instance: object) None

Удалите instance из этого Session.

Выступает от имени класса Session от имени класса scoped_session.

Это освободит все внутренние ссылки на экземпляр. Каскадирование будет применяться в соответствии с правилом каскада expunge.

method sqlalchemy.orm.scoped_session.expunge_all() None

Удалить все экземпляры объектов из данного Session.

Выступает от имени класса Session от имени класса scoped_session.

Это эквивалентно вызову expunge(obj) на всех объектах в этом Session.

method sqlalchemy.orm.scoped_session.flush(objects: Optional[Sequence[Any]] = None) None

Сбросьте все изменения объекта в базу данных.

Выступает от имени класса Session от имени класса scoped_session.

Записывает все ожидающие создания, удаления и модификации объектов в базу данных в виде INSERTs, DELETEs, UPDATEs и т.д. Операции автоматически упорядочиваются решателем зависимостей единицы работы сессии.

Операции с базой данных будут выполняться в текущем транзакционном контексте и не влияют на состояние транзакции, если только не произойдет ошибка, в этом случае вся транзакция будет откачена. Вы можете выполнять flush() так часто, как вам нравится в рамках транзакции, чтобы перенести изменения из Python в буфер транзакции базы данных.

Параметры:

objects – Необязательно; ограничивает операцию flush только элементами, которые находятся в данной коллекции. Эта функция предназначена для очень узкого круга случаев, когда конкретные объекты могут быть обработаны до того, как произойдет полная операция flush(). Она не предназначена для общего использования.

method sqlalchemy.orm.scoped_session.get(entity: _EntityBindKey[_O], ident: _PKIdentityArgument, *, options: Optional[Sequence[ORMOption]] = None, populate_existing: bool = False, with_for_update: ForUpdateParameter = None, identity_token: Optional[Any] = None, execution_options: OrmExecuteOptionsParameter = {}, bind_arguments: Optional[_BindArguments] = None) Optional[_O]

Возвращает экземпляр, основанный на заданном идентификаторе первичного ключа, или None, если он не найден.

Выступает от имени класса Session от имени класса scoped_session.

Например:

my_user = session.get(User, 5)

some_object = session.get(VersionedFoo, (5, 10))

some_object = session.get(
    VersionedFoo,
    {"id": 5, "version_id": 10}
)

Добавлено в версии 1.4: Добавлен метод Session.get(), который перенесен из устаревшего метода Query.get().

Session.get() является особенным, так как предоставляет прямой доступ к карте идентификации Session. Если заданный идентификатор первичного ключа присутствует в локальной карте идентификации, объект возвращается непосредственно из этой коллекции и никакого SQL не выдается, если только объект не был помечен как полностью истекший. Если он отсутствует, то для поиска объекта выполняется SELECT.

Session.get() также выполнит проверку, если объект присутствует в карте идентификации и помечен как просроченный - будет выдан SELECT, чтобы обновить объект, а также убедиться, что строка все еще присутствует. Если нет, то выдается сообщение ObjectDeletedError.

Параметры:
  • entity – сопоставленный класс или Mapper, указывающий на тип загружаемой сущности.

  • ident – Скаляр, кортеж или словарь, представляющий первичный ключ. Для составного (например, с несколькими столбцами) первичного ключа следует передавать кортеж или словарь. Для первичного ключа, состоящего из одного столбца, обычно наиболее удобна скалярная форма вызова. Если первичным ключом строки является значение «5», вызов выглядит так:: my_object = session.get(SomeClass, 5) Форма кортежа содержит значения первичного ключа обычно в том порядке, в котором они соответствуют столбцам первичного ключа сопоставленного объекта Table, или, если используется параметр конфигурации Mapper.primary_key, в порядке, используемом для этого параметра. Например, если первичный ключ строки представлен целыми цифрами «5, 10», вызов будет выглядеть так:: my_object = session.get(SomeClass, (5, 10)) Словарная форма должна включать в качестве ключей имена сопоставленных атрибутов, соответствующих каждому элементу первичного ключа. Если сопоставленный класс имеет атрибуты id, version_id в качестве атрибутов, которые хранят значение первичного ключа объекта, вызов будет выглядеть так:: my_object = session.get(SomeClass, {«id»: 5, «version_id»: 10})

  • options – необязательная последовательность опций загрузчика, которые будут применены к запросу, если таковой будет выдан.

  • populate_existing – заставляет метод безусловно выполнить SQL-запрос и обновить объект новыми загруженными данными, независимо от того, присутствует ли в нем уже данный объект.

  • with_for_updateTrue Query.with_for_update() Session.refresh.lockmode o

  • execution_optionsConnection.execution_options() Варианты выполнения ORM o

  • bind_arguments – :meth:`.Session.get_bind`d

Результат:

``None``T

method sqlalchemy.orm.scoped_session.get_bind(mapper: Optional[_EntityBindKey[_O]] = None, *, clause: Optional[ClauseElement] = None, bind: Optional[_SessionBind] = None, _sa_skip_events: Optional[bool] = None, _sa_skip_for_implicit_returning: bool = False, **kw: Any) Union[Engine, Connection]

:class:`.Session`R

Выступает от имени класса Session от имени класса scoped_session.

Engine Session Connection T

Session mapper clause F

Session.get_bind() Session.query() Session.flush() N

Порядок разрешения следующий:

  1. Session.binds __mro__ i

  2. Session.binds Table Session.binds i

  3. ``Session.binds``i

  4. :class:`_schema.MetaData`i

  5. MetaData Table i

  6. :exc:`~sqlalchemy.exc.UnboundExecutionError`N

Session.get_bind() Session Нестандартные вертикальные перегородки N

Параметры:
classmethod sqlalchemy.orm.scoped_session.identity_key(class_: Optional[Type[Any]] = None, ident: Union[Any, Tuple[Any, ...]] = None, *, instance: Optional[Any] = None, row: Optional[Union[Row[Any], RowMapping]] = None, identity_token: Optional[Any] = None) _IdentityKeyType[Any]

Возвращает ключ идентификации.

Выступает от имени класса Session от имени класса scoped_session.

:func:`.util.identity_key`T

attribute sqlalchemy.orm.scoped_session.identity_map

Прокси для атрибута Session.identity_map от имени класса scoped_session.

attribute sqlalchemy.orm.scoped_session.info

Модифицируемый пользователем словарь.

Выступает от имени класса Session от имени класса scoped_session.

info Session sessionmaker Session Session T

attribute sqlalchemy.orm.scoped_session.is_active

:class:`.Session`T

Выступает от имени класса Session от имени класса scoped_session.

Изменено в версии 1.4: Session Session T

Session Session.rollback() «

Session Session Session.is_active I

Session Session.is_active O

method sqlalchemy.orm.scoped_session.is_modified(instance: object, include_collections: bool = True) bool

``True``R

Выступает от имени класса Session от имени класса scoped_session.

Этот метод извлекает историю для каждого инструментального атрибута экземпляра и выполняет сравнение текущего значения с его ранее зафиксированным значением, если таковое имеется.

:attr:`.Session.dirty`I

Например:

return session.is_modified(someobject)

К этому методу есть несколько оговорок:

  • Session.dirty False Session.dirty I

  • Скалярные атрибуты могут не записать ранее установленное значение при применении нового значения, если атрибут не был загружен или его срок действия истек к моменту получения нового значения - в этих случаях предполагается, что атрибут изменился, даже если в конечном итоге никаких изменений по сравнению с его значением в базе данных не произошло. SQLAlchemy в большинстве случаев не нуждается в «старом» значении при наступлении события set, поэтому она пропускает затраты на вызов SQL, если старое значение отсутствует, исходя из предположения, что UPDATE скалярного значения обычно необходим, а в тех немногих случаях, когда это не так, в среднем обходится дешевле, чем выдача защитного SELECT.

    active_history True active_history column_property() T

Параметры:
  • instance – сопоставленный экземпляр, который должен быть проверен на наличие предстоящих изменений.

  • include_collections``False``I

method sqlalchemy.orm.scoped_session.merge(instance: _O, *, load: bool = True, options: Optional[Sequence[ORMOption]] = None) _O

:class:`.Session`C

Выступает от имени класса Session от имени класса scoped_session.

Session.merge() Session <

``cascade=»merge»``T

:ref:`unitofwork_merging`S

Параметры:
  • instance – Экземпляр, подлежащий объединению.

  • loadmerge() Session Session load=False Session load=False B

  • options – :meth:`_orm.Session.get`o

attribute sqlalchemy.orm.scoped_session.new

``Session``T

Выступает от имени класса Session от имени класса scoped_session.

attribute sqlalchemy.orm.scoped_session.no_autoflush

Возвращает менеджер контекста, в котором отключена автопромывка.

Выступает от имени класса Session от имени класса scoped_session.

например:

with session.no_autoflush:

    some_object = SomeClass()
    session.add(some_object)
    # won't autoflush
    some_object.related_thing = session.query(SomeRelated).first()

``with:``O

classmethod sqlalchemy.orm.scoped_session.object_session(instance: object) Optional[Session]

:class:`.Session`R

Выступает от имени класса Session от имени класса scoped_session.

:func:`.object_session`T

method sqlalchemy.orm.scoped_session.query(*entities: _ColumnsClauseArgument[Any], **kwargs: Any) Query[Any]

Query Session R

Выступает от имени класса Session от имени класса scoped_session.

Query select() N

method sqlalchemy.orm.scoped_session.query_property(query_cls: Optional[Type[Query[_T]]] = None) QueryPropertyDescriptor

Query Session r

например:

from sqlalchemy.orm import QueryPropertyDescriptor
from sqlalchemy.orm import scoped_session
from sqlalchemy.orm import sessionmaker

Session = scoped_session(sessionmaker())

class MyClass:
    query: QueryPropertyDescriptor = Session.query_property()

# after mappers are defined
result = MyClass.query.filter(MyClass.name=='foo').all()

``query_cls``P

Количество свойств запроса, размещаемых на классе, не ограничено.

method sqlalchemy.orm.scoped_session.refresh(instance: object, attribute_names: Optional[Iterable[str]] = None, with_for_update: ForUpdateParameter = None) None

Истечение срока действия и обновление атрибутов для данного экземпляра.

Выступает от имени класса Session от имени класса scoped_session.

:meth:`_orm.Session.expire`T

:func:`_orm.relationship`<

Добавлено в версии 1.4: Session.refresh()-

relationship() select immediate Session.refresh.attribute_names <

Изменено в версии 2.0.4: Session.refresh() relationship() Session.refresh.attribute_names T

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

Параметры:
  • attribute_names – опционально. Итерабельная коллекция строковых имен атрибутов, указывающих на подмножество атрибутов, которые необходимо обновить.

  • with_for_updateTrue Query.with_for_update() Session.refresh.lockmode o

См.также

Обновление / истечение срока действия - вводный материал

Session.expire()

Session.expire_all()

:ref:`orm_queryguide_populate_existing`<

method sqlalchemy.orm.scoped_session.remove() None

:class:`.Session`D

Session.close() Session Session scoped_session Session T

method sqlalchemy.orm.scoped_session.rollback() None

Откат текущей выполняемой транзакции.

Выступает от имени класса Session от имени класса scoped_session.

Если сделка не проводится, то данный метод является сквозным.

Метод всегда откатывает самую верхнюю транзакцию базы данных, отбрасывая все вложенные транзакции, которые могут находиться в процессе выполнения.

method sqlalchemy.orm.scoped_session.scalar(statement: Executable, params: Optional[_CoreSingleExecuteParams] = None, *, execution_options: OrmExecuteOptionsParameter = {}, bind_arguments: Optional[_BindArguments] = None, **kw: Any) Any

Выполнить оператор и вернуть скалярный результат.

Выступает от имени класса Session от имени класса scoped_session.

:meth:`_orm.Session.execute`U

method sqlalchemy.orm.scoped_session.scalars(statement: Executable, params: Optional[_CoreAnyExecuteParams] = None, *, execution_options: OrmExecuteOptionsParameter = {}, bind_arguments: Optional[_BindArguments] = None, **kw: Any) ScalarResult[Any]

Выполнить оператор и вернуть результаты в виде скаляров.

Выступает от имени класса Session от имени класса scoped_session.

Session.execute() ScalarResult Row U

Результат:

:class:`_result.ScalarResult`a

Добавлено в версии 1.4.24: :meth:`_orm.Session.scalars`A

Добавлено в версии 1.4.26: :meth:`_orm.scoped_session.scalars`A

attribute sqlalchemy.orm.scoped_session.session_factory: sessionmaker[_S]

session_factory provided to _ :class:.Session` T

class sqlalchemy.util.ScopedRegistry

Реестр, который может хранить один или несколько экземпляров одного класса на основе функции «scope».

__call__ myregistry() T

Параметры:
  • createfunc – вызываемый объект, который возвращает новый объект, помещаемый в реестр

  • scopefunc – вызываемый элемент, который возвращает ключ для хранения/получения объекта.

Классная подпись

класс sqlalchemy.util.ScopedRegistry (typing.Generic)

method sqlalchemy.util.ScopedRegistry.__init__(createfunc: Callable[[], _T], scopefunc: Callable[[], Any])

Создайте новый ScopedRegistry.

Параметры:
  • createfunc – Функция создания, которая генерирует новое значение для текущей области видимости, если таковое отсутствует.

  • scopefunc – Функция, возвращающая хэшируемый токен, представляющий текущую область видимости (например, идентификатор текущего потока).

method sqlalchemy.util.ScopedRegistry.clear() None

Очистить текущую область видимости, если таковая имеется.

method sqlalchemy.util.ScopedRegistry.has() bool

Возвращает True, если объект присутствует в текущей области видимости.

method sqlalchemy.util.ScopedRegistry.set(obj: _T) None

Установить значение для текущей области видимости.

class sqlalchemy.util.ThreadLocalRegistry

ScopedRegistry, который использует переменную threading.local() для хранения.

Классная подпись

класс sqlalchemy.util.ThreadLocalRegistry (sqlalchemy.util.ScopedRegistry)

class sqlalchemy.orm.QueryPropertyDescriptor

Описывает тип, применяемый к атрибуту уровня класса scoped_session.query_property().

Добавлено в версии 2.0.5.

Классная подпись

класс sqlalchemy.orm.QueryPropertyDescriptor (typing.Protocol)

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