want to work with them again, so that they can resume their normal task of
representing database state.
+.. _session_getting:
+
Getting a Session
=================
example's sake! In reality, the :class:`.sessionmaker` would be somewhere
at the module level. The calls to instantiate :class:`.Session`
would then be placed at the point in the application where database
- conversations begin (see :ref:`session_faq_whentocreate`).
+ conversations begin.
* When do I construct a :class:`.Session`, when do I commit it, and when do I close it ?
begin a new transaction if it is used again, subsequent to the previous
transaction ending; from this it follows that the :class:`.Session`
is capable of having a lifespan across many transactions, though only
- one at a time. We refer to these two concepts as *transaction scope*
- and *session scope*.
+ one at a time. We refer to these two concepts as **transaction scope**
+ and **session scope**.
The implication here is that the SQLAlchemy ORM is encouraging the
developer to establish these two scopes in his or her application,
pattern which establishes one as soon as it is needed. The request
then proceeds, with some system in place where application logic can access
the current :class:`.Session` in a manner associated with how the actual
- requset object is accessed. As the request ends, the :class:`.Session`
+ request object is accessed. As the request ends, the :class:`.Session`
is torn down as well, usually through the usage of event hooks provided
by the web framework. The transaction used by the :class:`.Session`
may also be committed at this point, or alternatively the application may
In those situations where integration libraries are not available,
SQLAlchemy includes its own "helper" class known as
- :class:`.scoped_session`. This object actually is used as the basis
- of some integration packages, and provides both a quick way
+ :class:`.scoped_session`. A tutorial on the usage of this object
+ is at :ref:`unitofwork_contextual`. It provides both a quick way
to associate a :class:`.Session` with the current thread, as well as
patterns to associate :class:`.Session` objects with other kinds of
scopes.
a series of operations for some period of time, which can be committed
at the end. Some examples:
- * A background daemon which spawns off child forks for example
+ * A background daemon which spawns off child forks
would want to create a :class:`.Session` local to each child
process work with that :class:`.Session` through the life of the "job"
that the fork is handling, then tear it down when the job is completed.
:class:`.Session` with a thread implies it is also associated with the web request
running within that thread, and vice versa, provided that the :class:`.Session` is
created only after the web request begins and torn down just before the web request ends.
-So it is a very common practice to use :class:`.scoped_session` as a quick way
+So it is a common practice to use :class:`.scoped_session` as a quick way
to integrate the :class:`.Session` with a web application. The sequence
diagram below illustrates this flow::
based on any existing system of getting at "the current thing we are working with".
Suppose a web framework defines a library function ``get_current_request()``. An application
-build on this framework can call this function at any time, and the result will be
+built using this framework can call this function at any time, and the result will be
some kind of ``Request`` object that represents the current request being processed.
If the ``Request`` object is hashable, then this function can be easily integrated with
:class:`.scoped_session` to associate the :class:`.Session` with the request. Below we illustrate
else:
self.registry = ThreadLocalRegistry(session_factory)
- def __call__(self, **kwargs):
- """Return the current :class:`.Session`."""
- if kwargs:
- scope = kwargs.pop('scope', False)
+ def __call__(self, **kw):
+ """Return the current :class:`.Session`, creating it
+ using the session factory if not present.
+
+ :param \**kw: Keyword arguments will be passed to the
+ session factory callable, if an existing :class:`.Session`
+ is not present. If the :class:`.Session` is present and
+ keyword arguments have been passed, :class:`.InvalidRequestError`
+ is raised.
+
+ """
+ if kw:
+ scope = kw.pop('scope', False)
if scope is not None:
if self.registry.has():
raise sa_exc.InvalidRequestError(
"Scoped session is already present; "
"no new arguments may be specified.")
else:
- sess = self.session_factory(**kwargs)
+ sess = self.session_factory(**kw)
self.registry.set(sess)
return sess
else:
- return self.session_factory(**kwargs)
+ return self.session_factory(**kw)
else:
return self.registry()
def remove(self):
- """Dispose of the current contextual session."""
+ """Dispose of the current :class:`.Session`, if present.
+
+ This will first call :meth:`.Session.close` method
+ on the current :class:`.Session`, which releases any existing
+ transactional/connection resources still being held; transactions
+ specifically are rolled back. The :class:`.Session` is then
+ discarded. Upon next usage within the same scope,
+ the :class:`.scoped_session` will produce a new
+ :class:`.Session` object.
+
+ """
if self.registry.has():
self.registry().close()