7
.. module:: sqlalchemy.orm.session
9
The :func:`.orm.mapper` function and :mod:`~sqlalchemy.ext.declarative` extensions
10
are the primary configurational interface for the ORM. Once mappings are
11
configured, the primary usage interface for persistence operations is the
14
What does the Session do ?
15
==========================
17
In the most general sense, the :class:`~.Session` establishes all
18
conversations with the database and represents a "holding zone" for all the
19
objects which you've loaded or associated with it during its lifespan. It
20
provides the entrypoint to acquire a :class:`.Query` object, which sends
21
queries to the database using the :class:`~.Session` object's current database
22
connection, populating result rows into objects that are then stored in the
23
:class:`.Session`, inside a structure called the `Identity Map
24
<http://martinfowler.com/eaaCatalog/identityMap.html>`_ - a data structure
25
that maintains unique copies of each object, where "unique" means "only one
26
object with a particular primary key".
28
The :class:`.Session` begins in an essentially stateless form. Once queries
29
are issued or other objects are persisted with it, it requests a connection
30
resource from an :class:`.Engine` that is associated either with the
31
:class:`.Session` itself or with the mapped :class:`.Table` objects being
32
operated upon. This connection represents an ongoing transaction, which
33
remains in effect until the :class:`.Session` is instructed to commit or roll
34
back its pending state.
36
All changes to objects maintained by a :class:`.Session` are tracked - before
37
the database is queried again or before the current transaction is committed,
38
it **flushes** all pending changes to the database. This is known as the `Unit
39
of Work <http://martinfowler.com/eaaCatalog/unitOfWork.html>`_ pattern.
41
When using a :class:`.Session`, it's important to note that the objects
42
which are associated with it are **proxy objects** to the transaction being
43
held by the :class:`.Session` - there are a variety of events that will cause
44
objects to re-access the database in order to keep synchronized. It is
45
possible to "detach" objects from a :class:`.Session`, and to continue using
46
them, though this practice has its caveats. It's intended that
47
usually, you'd re-associate detached objects another :class:`.Session` when you
48
want to work with them again, so that they can resume their normal task of
49
representing database state.
54
:class:`.Session` is a regular Python class which can
55
be directly instantiated. However, to standardize how sessions are configured
56
and acquired, the :func:`.sessionmaker` function is normally
57
used to create a top level :class:`.Session`
58
configuration which can then be used throughout an application without the
59
need to repeat the configurational arguments.
61
The usage of :func:`.sessionmaker` is illustrated below:
63
.. sourcecode:: python+sql
65
from sqlalchemy.orm import sessionmaker
67
# create a configured "Session" class
68
Session = sessionmaker(bind=some_engine)
74
myobject = MyObject('foo', 'bar')
78
Above, the :func:`.sessionmaker` call creates a class for us,
79
which we assign to the name ``Session``. This class is a subclass of the
80
actual :class:`.Session` class, which when instantiated, will
81
use the arguments we've given the function, in this case
82
to use a particular :class:`.Engine` for connection resources.
84
When you write your application, place the call to
85
:func:`.sessionmaker` somewhere global, and then make your new
86
``Session`` class available to the rest of your application.
88
A typical setup will associate the :func:`.sessionmaker` with an :class:`.Engine`,
89
so that each :class:`.Session` generated will use this :class:`.Engine`
90
to acquire connection resources. This association can
91
be set up as in the example above, using the ``bind`` argument. You
92
can also associate a :class:`.Engine` with an existing :func:`.sessionmaker`
93
using the :meth:`.sessionmaker.configure` method::
95
from sqlalchemy.orm import sessionmaker
96
from sqlalchemy import create_engine
98
# configure Session class with desired options
99
Session = sessionmaker()
101
# later, we create the engine
102
engine = create_engine('postgresql://...')
104
# associate it with our custom Session class
105
Session.configure(bind=engine)
107
# work with the session
110
you can also associate individual :class:`.Session` objects with an :class:`.Engine`
113
session = Session(bind=engine)
115
...or directly with a :class:`.Connection`::
117
conn = engine.connect()
118
session = Session(bind=conn)
120
While the rationale for the above example may not be apparent, the typical
121
usage is in a test fixture that maintains an external transaction - see
122
:ref:`session_external_transaction` below for a full example.
127
Quickie Intro to Object States
128
------------------------------
130
It's helpful to know the states which an instance can have within a session:
132
* *Transient* - an instance that's not in a session, and is not saved to the
133
database; i.e. it has no database identity. The only relationship such an
134
object has to the ORM is that its class has a ``mapper()`` associated with
137
* *Pending* - when you :func:`~sqlalchemy.orm.session.Session.add` a transient
138
instance, it becomes pending. It still wasn't actually flushed to the
139
database yet, but it will be when the next flush occurs.
141
* *Persistent* - An instance which is present in the session and has a record
142
in the database. You get persistent instances by either flushing so that the
143
pending instances become persistent, or by querying the database for
144
existing instances (or moving persistent instances from other sessions into
147
* *Detached* - an instance which has a record in the database, but is not in
148
any session. There's nothing wrong with this, and you can use objects
149
normally when they're detached, **except** they will not be able to issue
150
any SQL in order to load collections or attributes which are not yet loaded,
151
or were marked as "expired".
153
Knowing these states is important, since the
154
:class:`~sqlalchemy.orm.session.Session` tries to be strict about ambiguous
155
operations (such as trying to save the same object to two different sessions
158
Frequently Asked Questions
159
--------------------------
161
* When do I make a :func:`.sessionmaker` ?
163
Just one time, somewhere in your application's global scope. It should be
164
looked upon as part of your application's configuration. If your
165
application has three .py files in a package, you could, for example,
166
place the :func:`.sessionmaker` line in your ``__init__.py`` file; from
167
that point on your other modules say "from mypackage import Session". That
168
way, everyone else just uses :class:`.Session()`,
169
and the configuration of that session is controlled by that central point.
171
If your application starts up, does imports, but does not know what
172
database it's going to be connecting to, you can bind the
173
:class:`.Session` at the "class" level to the
174
engine later on, using ``configure()``.
176
In the examples in this section, we will frequently show the
177
:func:`.sessionmaker` being created right above the line where we actually
178
invoke :class:`~sqlalchemy.orm.session.Session()`. But that's just for
179
example's sake ! In reality, the :func:`.sessionmaker` would be somewhere
180
at the module level, and your individual
181
:class:`~sqlalchemy.orm.session.Session()` calls would be sprinkled all
182
throughout your app, such as in a web application within each controller
185
* When do I make a :class:`.Session` ?
187
You typically invoke :class:`.Session` when you first need to talk to your
188
database, and want to save some objects or load some existing ones. It
189
then remains in use for the lifespan of a particular database
190
conversation, which includes not just the initial loading of objects but
191
throughout the whole usage of those instances.
193
Objects become detached if their owning session is discarded. They are
194
still functional in the detached state if the user has ensured that their
195
state has not been expired before detachment, but they will not be able to
196
represent the current state of database data. Because of this, it's best
197
to consider persisted objects as an extension of the state of a particular
198
:class:`.Session`, and to keep that session around until all referenced
199
objects have been discarded.
201
An exception to this is when objects are placed in caches or otherwise
202
shared among threads or processes, in which case their detached state can
203
be stored, transmitted, or shared. However, the state of detached objects
204
should still be transferred back into a new :class:`.Session` using
205
:meth:`.Session.add` or :meth:`.Session.merge` before working with the
206
object (or in the case of merge, its state) again.
208
It is also very common that a :class:`.Session` as well as its associated
209
objects are only referenced by a single thread. Sharing objects between
210
threads is most safely accomplished by sharing their state among multiple
211
instances of those objects, each associated with a distinct
212
:class:`.Session` per thread, :meth:`.Session.merge` to transfer state
213
between threads. This pattern is not a strict requirement by any means,
214
but it has the least chance of introducing concurrency issues.
216
To help with the recommended :class:`.Session` -per-thread,
217
:class:`.Session` -per-set-of-objects patterns, the
218
:func:`.scoped_session` function is provided which produces a
219
thread-managed registry of :class:`.Session` objects. It is commonly used
220
in web applications so that a single global variable can be used to safely
221
represent transactional sessions with sets of objects, localized to a
222
single thread. More on this object is in :ref:`unitofwork_contextual`.
224
* Is the Session a cache ?
226
Yeee...no. It's somewhat used as a cache, in that it implements the
227
identity map pattern, and stores objects keyed to their primary key.
228
However, it doesn't do any kind of query caching. This means, if you say
229
``session.query(Foo).filter_by(name='bar')``, even if ``Foo(name='bar')``
230
is right there, in the identity map, the session has no idea about that.
231
It has to issue SQL to the database, get the rows back, and then when it
232
sees the primary key in the row, *then* it can look in the local identity
233
map and see that the object is already there. It's only when you say
234
``query.get({some primary key})`` that the
235
:class:`~sqlalchemy.orm.session.Session` doesn't have to issue a query.
237
Additionally, the Session stores object instances using a weak reference
238
by default. This also defeats the purpose of using the Session as a cache.
240
The :class:`.Session` is not designed to be a
241
global object from which everyone consults as a "registry" of objects.
242
That's more the job of a **second level cache**. SQLAlchemy provides
243
a pattern for implementing second level caching using `Beaker <http://beaker.groovie.org/>`_,
244
via the :ref:`examples_caching` example.
246
* How can I get the :class:`~sqlalchemy.orm.session.Session` for a certain object ?
248
Use the :func:`~sqlalchemy.orm.session.Session.object_session` classmethod
249
available on :class:`~sqlalchemy.orm.session.Session`::
251
session = Session.object_session(someobject)
254
single: thread safety; sessions
255
single: thread safety; Session
257
* Is the session thread-safe?
259
Nope. It has no thread synchronization of any kind built in, and
260
particularly when you do a flush operation, it definitely is not open to
261
concurrent threads accessing it, because it holds onto a single database
262
connection at that point. If you use a session which is non-transactional
263
(meaning, ``autocommit`` is set to ``True``, not the default setting)
264
for read operations only, it's still not thread-"safe", but you also wont
265
get any catastrophic failures either, since it checks out and returns
266
connections to the connection pool on an as-needed basis; it's just that
267
different threads might load the same objects independently of each other,
268
but only one will wind up in the identity map (however, the other one
269
might still live in a collection somewhere).
271
But the bigger point here is, you should not *want* to use the session
272
with multiple concurrent threads. That would be like having everyone at a
273
restaurant all eat from the same plate. The session is a local "workspace"
274
that you use for a specific set of tasks; you don't want to, or need to,
275
share that session with other threads who are doing some other task. If,
276
on the other hand, there are other threads participating in the same task
277
you are, such as in a desktop graphical application, then you would be
278
sharing the session with those threads, but you also will have implemented
279
a proper locking scheme (or your graphical framework does) so that those
280
threads do not collide.
282
A multithreaded application is usually going to want to make usage of
283
:func:`.scoped_session` to transparently manage sessions per thread.
284
More on this at :ref:`unitofwork_contextual`.
289
The :func:`~sqlalchemy.orm.session.Session.query` function takes one or more
290
*entities* and returns a new :class:`~sqlalchemy.orm.query.Query` object which
291
will issue mapper queries within the context of this Session. An entity is
292
defined as a mapped class, a :class:`~sqlalchemy.orm.mapper.Mapper` object, an
293
orm-enabled *descriptor*, or an ``AliasedClass`` object::
296
session.query(User).filter_by(name='ed').all()
298
# query with multiple classes, returns tuples
299
session.query(User, Address).join('addresses').filter_by(name='ed').all()
301
# query using orm-enabled descriptors
302
session.query(User.name, User.fullname).all()
304
# query from a mapper
305
user_mapper = class_mapper(User)
306
session.query(user_mapper)
308
When :class:`~sqlalchemy.orm.query.Query` returns results, each object
309
instantiated is stored within the identity map. When a row matches an object
310
which is already present, the same object is returned. In the latter case,
311
whether or not the row is populated onto an existing object depends upon
312
whether the attributes of the instance have been *expired* or not. A
313
default-configured :class:`~sqlalchemy.orm.session.Session` automatically
314
expires all instances along transaction boundaries, so that with a normally
315
isolated transaction, there shouldn't be any issue of instances representing
316
data which is stale with regards to the current transaction.
318
The :class:`.Query` object is introduced in great detail in
319
:ref:`ormtutorial_toplevel`, and further documented in
320
:ref:`query_api_toplevel`.
322
Adding New or Existing Items
323
----------------------------
325
:func:`~sqlalchemy.orm.session.Session.add` is used to place instances in the
326
session. For *transient* (i.e. brand new) instances, this will have the effect
327
of an INSERT taking place for those instances upon the next flush. For
328
instances which are *persistent* (i.e. were loaded by this session), they are
329
already present and do not need to be added. Instances which are *detached*
330
(i.e. have been removed from a session) may be re-associated with a session
333
user1 = User(name='user1')
334
user2 = User(name='user2')
338
session.commit() # write changes to the database
340
To add a list of items to the session at once, use
341
:func:`~sqlalchemy.orm.session.Session.add_all`::
343
session.add_all([item1, item2, item3])
345
The :func:`~sqlalchemy.orm.session.Session.add` operation **cascades** along
346
the ``save-update`` cascade. For more details see the section
347
:ref:`unitofwork_cascades`.
349
.. _unitofwork_merging:
354
:func:`~sqlalchemy.orm.session.Session.merge` reconciles the current state of
355
an instance and its associated children with existing data in the database,
356
and returns a copy of the instance associated with the session. Usage is as
359
merged_object = session.merge(existing_object)
361
When given an instance, it follows these steps:
363
* It examines the primary key of the instance. If it's present, it attempts
364
to load an instance with that primary key (or pulls from the local
366
* If there's no primary key on the given instance, or the given primary key
367
does not exist in the database, a new instance is created.
368
* The state of the given instance is then copied onto the located/newly
370
* The operation is cascaded to associated child items along the ``merge``
371
cascade. Note that all changes present on the given instance, including
372
changes to collections, are merged.
373
* The new instance is returned.
375
With :func:`~sqlalchemy.orm.session.Session.merge`, the given instance is not
376
placed within the session, and can be associated with a different session or
377
detached. :func:`~sqlalchemy.orm.session.Session.merge` is very useful for
378
taking the state of any kind of object structure without regard for its
379
origins or current session associations and placing that state within a
380
session. Here's two examples:
382
* An application which reads an object structure from a file and wishes to
383
save it to the database might parse the file, build up the
384
structure, and then use
385
:func:`~sqlalchemy.orm.session.Session.merge` to save it
386
to the database, ensuring that the data within the file is
387
used to formulate the primary key of each element of the
388
structure. Later, when the file has changed, the same
389
process can be re-run, producing a slightly different
390
object structure, which can then be ``merged`` in again,
391
and the :class:`~sqlalchemy.orm.session.Session` will
392
automatically update the database to reflect those
394
* A web application stores mapped entities within an HTTP session object.
395
When each request starts up, the serialized data can be
396
merged into the session, so that the original entity may
397
be safely shared among requests and threads.
399
:func:`~sqlalchemy.orm.session.Session.merge` is frequently used by
400
applications which implement their own second level caches. This refers to an
401
application which uses an in memory dictionary, or an tool like Memcached to
402
store objects over long running spans of time. When such an object needs to
403
exist within a :class:`~sqlalchemy.orm.session.Session`,
404
:func:`~sqlalchemy.orm.session.Session.merge` is a good choice since it leaves
405
the original cached object untouched. For this use case, merge provides a
406
keyword option called ``load=False``. When this boolean flag is set to
407
``False``, :func:`~sqlalchemy.orm.session.Session.merge` will not issue any
408
SQL to reconcile the given object against the current state of the database,
409
thereby reducing query overhead. The limitation is that the given object and
410
all of its children may not contain any pending changes, and it's also of
411
course possible that newer information in the database will not be present on
412
the merged object, since no load is issued.
417
:meth:`~.Session.merge` is an extremely useful method for many purposes. However,
418
it deals with the intricate border between objects that are transient/detached and
419
those that are persistent, as well as the automated transferrence of state.
420
The wide variety of scenarios that can present themselves here often require a
421
more careful approach to the state of objects. Common problems with merge usually involve
422
some unexpected state regarding the object being passed to :meth:`~.Session.merge`.
424
Lets use the canonical example of the User and Address objects::
427
__tablename__ = 'user'
429
id = Column(Integer, primary_key=True)
430
name = Column(String(50), nullable=False)
431
addresses = relationship("Address", backref="user")
434
__tablename__ = 'address'
436
id = Column(Integer, primary_key=True)
437
email_address = Column(String(50), nullable=False)
438
user_id = Column(Integer, ForeignKey('user.id'), nullable=False)
440
Assume a ``User`` object with one ``Address``, already persistent::
442
>>> u1 = User(name='ed', addresses=[Address(email_address='ed@ed.com')])
446
We now create ``a1``, an object outside the session, which we'd like
447
to merge on top of the existing ``Address``::
449
>>> existing_a1 = u1.addresses[0]
450
>>> a1 = Address(id=existing_a1.id)
452
A surprise would occur if we said this::
455
>>> a1 = session.merge(a1)
457
sqlalchemy.orm.exc.FlushError: New instance <Address at 0x1298f50>
458
with identity key (<class '__main__.Address'>, (1,)) conflicts with
459
persistent instance <Address at 0x12a25d0>
461
Why is that ? We weren't careful with our cascades. The assignment
462
of ``a1.user`` to a persistent object cascaded to the backref of ``User.addresses``
463
and made our ``a1`` object pending, as though we had added it. Now we have
464
*two* ``Address`` objects in the session::
470
>>> existing_a1 in session
472
>>> a1 is existing_a1
475
Above, our ``a1`` is already pending in the session. The
476
subsequent :meth:`~.Session.merge` operation essentially
477
does nothing. Cascade can be configured via the ``cascade``
478
option on :func:`.relationship`, although in this case it
479
would mean removing the ``save-update`` cascade from the
480
``User.addresses`` relationship - and usually, that behavior
481
is extremely convenient. The solution here would usually be to not assign
482
``a1.user`` to an object already persistent in the target
485
Note that a new :func:`.relationship` option introduced in 0.6.5,
486
``cascade_backrefs=False``, will also prevent the ``Address`` from
487
being added to the session via the ``a1.user = u1`` assignment.
489
Further detail on cascade operation is at :ref:`unitofwork_cascades`.
491
Another example of unexpected state::
493
>>> a1 = Address(id=existing_a1.id, user_id=u1.id)
494
>>> assert a1.user is None
496
>>> a1 = session.merge(a1)
498
sqlalchemy.exc.IntegrityError: (IntegrityError) address.user_id
501
Here, we accessed a1.user, which returned its default value
502
of ``None``, which as a result of this access, has been placed in the ``__dict__`` of
503
our object ``a1``. Normally, this operation creates no change event,
504
so the ``user_id`` attribute takes precedence during a
505
flush. But when we merge the ``Address`` object into the session, the operation
508
>>> existing_a1.id = existing_a1.id
509
>>> existing_a1.user_id = u1.id
510
>>> existing_a1.user = None
512
Where above, both ``user_id`` and ``user`` are assigned to, and change events
513
are emitted for both. The ``user`` association
514
takes precedence, and None is applied to ``user_id``, causing a failure.
516
Most :meth:`~.Session.merge` issues can be examined by first checking -
517
is the object prematurely in the session ?
519
.. sourcecode:: python+sql
521
>>> a1 = Address(id=existing_a1, user_id=user.id)
522
>>> assert a1 not in session
523
>>> a1 = session.merge(a1)
525
Or is there state on the object that we don't want ? Examining ``__dict__``
526
is a quick way to check::
528
>>> a1 = Address(id=existing_a1, user_id=user.id)
531
{'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x1298d10>,
535
>>> # we don't want user=None merged, remove it
537
>>> a1 = session.merge(a1)
544
The :func:`~sqlalchemy.orm.session.Session.delete` method places an instance
545
into the Session's list of objects to be marked as deleted::
547
# mark two objects to be deleted
554
The big gotcha with :func:`~sqlalchemy.orm.session.Session.delete` is that
555
**nothing is removed from collections**. Such as, if a ``User`` has a
556
collection of three ``Addresses``, deleting an ``Address`` will not remove it
557
from ``user.addresses``::
559
>>> address = user.addresses[1]
560
>>> session.delete(address)
562
>>> address in user.addresses
565
The solution is to use proper cascading::
567
mapper(User, users_table, properties={
568
'addresses':relationship(Address, cascade="all, delete, delete-orphan")
570
del user.addresses[1]
573
Deleting based on Filter Criterion
574
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
576
The caveat with ``Session.delete()`` is that you need to have an object handy
577
already in order to delete. The Query includes a
578
:func:`~sqlalchemy.orm.query.Query.delete` method which deletes based on
581
session.query(User).filter(User.id==7).delete()
583
The ``Query.delete()`` method includes functionality to "expire" objects
584
already in the session which match the criteria. However it does have some
585
caveats, including that "delete" and "delete-orphan" cascades won't be fully
586
expressed for collections which are already loaded. See the API docs for
587
:meth:`~sqlalchemy.orm.query.Query.delete` for more details.
592
When the :class:`~sqlalchemy.orm.session.Session` is used with its default
593
configuration, the flush step is nearly always done transparently.
594
Specifically, the flush occurs before any individual
595
:class:`~sqlalchemy.orm.query.Query` is issued, as well as within the
596
:func:`~sqlalchemy.orm.session.Session.commit` call before the transaction is
597
committed. It also occurs before a SAVEPOINT is issued when
598
:func:`~sqlalchemy.orm.session.Session.begin_nested` is used.
600
Regardless of the autoflush setting, a flush can always be forced by issuing
601
:func:`~sqlalchemy.orm.session.Session.flush`::
605
The "flush-on-Query" aspect of the behavior can be disabled by constructing
606
:func:`.sessionmaker` with the flag ``autoflush=False``::
608
Session = sessionmaker(autoflush=False)
610
Additionally, autoflush can be temporarily disabled by setting the
611
``autoflush`` flag at any time::
613
mysession = Session()
614
mysession.autoflush = False
616
Some autoflush-disable recipes are available at `DisableAutoFlush
617
<http://www.sqlalchemy.org/trac/wiki/UsageRecipes/DisableAutoflush>`_.
619
The flush process *always* occurs within a transaction, even if the
620
:class:`~sqlalchemy.orm.session.Session` has been configured with
621
``autocommit=True``, a setting that disables the session's persistent
622
transactional state. If no transaction is present,
623
:func:`~sqlalchemy.orm.session.Session.flush` creates its own transaction and
624
commits it. Any failures during flush will always result in a rollback of
625
whatever transaction is present. If the Session is not in ``autocommit=True``
626
mode, an explicit call to :func:`~sqlalchemy.orm.session.Session.rollback` is
627
required after a flush fails, even though the underlying transaction will have
628
been rolled back already - this is so that the overall nesting pattern of
629
so-called "subtransactions" is consistently maintained.
634
:func:`~sqlalchemy.orm.session.Session.commit` is used to commit the current
635
transaction. It always issues :func:`~sqlalchemy.orm.session.Session.flush`
636
beforehand to flush any remaining state to the database; this is independent
637
of the "autoflush" setting. If no transaction is present, it raises an error.
638
Note that the default behavior of the :class:`~sqlalchemy.orm.session.Session`
639
is that a transaction is always present; this behavior can be disabled by
640
setting ``autocommit=True``. In autocommit mode, a transaction can be
641
initiated by calling the :func:`~sqlalchemy.orm.session.Session.begin` method.
643
Another behavior of :func:`~sqlalchemy.orm.session.Session.commit` is that by
644
default it expires the state of all instances present after the commit is
645
complete. This is so that when the instances are next accessed, either through
646
attribute access or by them being present in a
647
:class:`~sqlalchemy.orm.query.Query` result set, they receive the most recent
648
state. To disable this behavior, configure
649
:func:`.sessionmaker` with ``expire_on_commit=False``.
651
Normally, instances loaded into the :class:`~sqlalchemy.orm.session.Session`
652
are never changed by subsequent queries; the assumption is that the current
653
transaction is isolated so the state most recently loaded is correct as long
654
as the transaction continues. Setting ``autocommit=True`` works against this
655
model to some degree since the :class:`~sqlalchemy.orm.session.Session`
656
behaves in exactly the same way with regard to attribute state, except no
657
transaction is present.
662
:func:`~sqlalchemy.orm.session.Session.rollback` rolls back the current
663
transaction. With a default configured session, the post-rollback state of the
664
session is as follows:
666
* All transactions are rolled back and all connections returned to the
667
connection pool, unless the Session was bound directly to a Connection, in
668
which case the connection is still maintained (but still rolled back).
669
* Objects which were initially in the *pending* state when they were added
670
to the :class:`~sqlalchemy.orm.session.Session` within the lifespan of the
671
transaction are expunged, corresponding to their INSERT statement being
672
rolled back. The state of their attributes remains unchanged.
673
* Objects which were marked as *deleted* within the lifespan of the
674
transaction are promoted back to the *persistent* state, corresponding to
675
their DELETE statement being rolled back. Note that if those objects were
676
first *pending* within the transaction, that operation takes precedence
678
* All objects not expunged are fully expired.
680
With that state understood, the :class:`~sqlalchemy.orm.session.Session` may
681
safely continue usage after a rollback occurs.
683
When a :func:`~sqlalchemy.orm.session.Session.flush` fails, typically for
684
reasons like primary key, foreign key, or "not nullable" constraint
685
violations, a :func:`~sqlalchemy.orm.session.Session.rollback` is issued
686
automatically (it's currently not possible for a flush to continue after a
687
partial failure). However, the flush process always uses its own transactional
688
demarcator called a *subtransaction*, which is described more fully in the
689
docstrings for :class:`~sqlalchemy.orm.session.Session`. What it means here is
690
that even though the database transaction has been rolled back, the end user
691
must still issue :func:`~sqlalchemy.orm.session.Session.rollback` to fully
692
reset the state of the :class:`~sqlalchemy.orm.session.Session`.
697
Expunge removes an object from the Session, sending persistent instances to
698
the detached state, and pending instances to the transient state:
700
.. sourcecode:: python+sql
702
session.expunge(obj1)
704
To remove all items, call :func:`~sqlalchemy.orm.session.Session.expunge_all`
705
(this method was formerly known as ``clear()``).
710
The :func:`~sqlalchemy.orm.session.Session.close` method issues a
711
:func:`~sqlalchemy.orm.session.Session.expunge_all`, and releases any
712
transactional/connection resources. When connections are returned to the
713
connection pool, transactional state is rolled back as well.
715
Refreshing / Expiring
716
---------------------
718
The Session normally works in the context of an ongoing transaction (with the
719
default setting of autoflush=False). Most databases offer "isolated"
720
transactions - this refers to a series of behaviors that allow the work within
721
a transaction to remain consistent as time passes, regardless of the
722
activities outside of that transaction. A key feature of a high degree of
723
transaction isolation is that emitting the same SELECT statement twice will
724
return the same results as when it was called the first time, even if the data
725
has been modified in another transaction.
727
For this reason, the :class:`.Session` gains very efficient behavior by
728
loading the attributes of each instance only once. Subsequent reads of the
729
same row in the same transaction are assumed to have the same value. The
730
user application also gains directly from this assumption, that the transaction
731
is regarded as a temporary shield against concurrent changes - a good application
732
will ensure that isolation levels are set appropriately such that this assumption
733
can be made, given the kind of data being worked with.
735
To clear out the currently loaded state on an instance, the instance or its individual
736
attributes can be marked as "expired", which results in a reload to
737
occur upon next access of any of the instance's attrbutes. The instance
738
can also be immediately reloaded from the database. The :meth:`~.Session.expire`
739
and :meth:`~.Session.refresh` methods achieve this::
741
# immediately re-load attributes on obj1, obj2
742
session.refresh(obj1)
743
session.refresh(obj2)
745
# expire objects obj1, obj2, attributes will be reloaded
746
# on the next access:
750
When an expired object reloads, all non-deferred column-based attributes are
751
loaded in one query. Current behavior for expired relationship-based
752
attributes is that they load individually upon access - this behavior may be
753
enhanced in a future release. When a refresh is invoked on an object, the
754
ultimate operation is equivalent to a :meth:`.Query.get`, so any relationships
755
configured with eager loading should also load within the scope of the refresh
758
:meth:`~.Session.refresh` and
759
:meth:`~.Session.expire` also support being passed a
760
list of individual attribute names in which to be refreshed. These names can
761
refer to any attribute, column-based or relationship based::
763
# immediately re-load the attributes 'hello', 'world' on obj1, obj2
764
session.refresh(obj1, ['hello', 'world'])
765
session.refresh(obj2, ['hello', 'world'])
767
# expire the attributes 'hello', 'world' objects obj1, obj2, attributes will be reloaded
768
# on the next access:
769
session.expire(obj1, ['hello', 'world'])
770
session.expire(obj2, ['hello', 'world'])
772
The full contents of the session may be expired at once using
773
:meth:`~.Session.expire_all`::
777
Note that :meth:`~.Session.expire_all` is called **automatically** whenever
778
:meth:`~.Session.commit` or :meth:`~.Session.rollback` are called. If using the
779
session in its default mode of autocommit=False and with a well-isolated
780
transactional environment (which is provided by most backends with the notable
781
exception of MySQL MyISAM), there is virtually *no reason* to ever call
782
:meth:`~.Session.expire_all` directly - plenty of state will remain on the
783
current transaction until it is rolled back or committed or otherwise removed.
785
:meth:`~.Session.refresh` and :meth:`~.Session.expire` similarly are usually
786
only necessary when an UPDATE or DELETE has been issued manually within the
787
transaction using :meth:`.Session.execute()`.
792
The :class:`~sqlalchemy.orm.session.Session` itself acts somewhat like a
793
set-like collection. All items present may be accessed using the iterator
799
And presence may be tested for using regular "contains" semantics::
802
print "Object is present"
804
The session is also keeping track of all newly created (i.e. pending) objects,
805
all objects which have had changes since they were last loaded or saved (i.e.
806
"dirty"), and everything that's been marked as deleted::
808
# pending objects recently added to the Session
811
# persistent objects which currently have changes detected
812
# (this collection is now created on the fly each time the property is called)
815
# persistent objects that have been marked as deleted via session.delete(obj)
818
Note that objects within the session are by default *weakly referenced*. This
819
means that when they are dereferenced in the outside application, they fall
820
out of scope from within the :class:`~sqlalchemy.orm.session.Session` as well
821
and are subject to garbage collection by the Python interpreter. The
822
exceptions to this include objects which are pending, objects which are marked
823
as deleted, or persistent objects which have pending changes on them. After a
824
full flush, these collections are all empty, and all objects are again weakly
825
referenced. To disable the weak referencing behavior and force all objects
826
within the session to remain until explicitly expunged, configure
827
:func:`.sessionmaker` with the ``weak_identity_map=False``
830
.. _unitofwork_cascades:
835
Mappers support the concept of configurable *cascade* behavior on
836
:func:`~sqlalchemy.orm.relationship` constructs. This behavior controls how
837
the Session should treat the instances that have a parent-child relationship
838
with another instance that is operated upon by the Session. Cascade is
839
indicated as a comma-separated list of string keywords, with the possible
840
values ``all``, ``delete``, ``save-update``, ``refresh-expire``, ``merge``,
841
``expunge``, and ``delete-orphan``.
843
Cascading is configured by setting the ``cascade`` keyword argument on a
844
:func:`~sqlalchemy.orm.relationship`::
846
mapper(Order, order_table, properties={
847
'items' : relationship(Item, items_table, cascade="all, delete-orphan"),
848
'customer' : relationship(User, users_table, user_orders_table, cascade="save-update"),
851
The above mapper specifies two relationships, ``items`` and ``customer``. The
852
``items`` relationship specifies "all, delete-orphan" as its ``cascade``
853
value, indicating that all ``add``, ``merge``, ``expunge``, ``refresh``
854
``delete`` and ``expire`` operations performed on a parent ``Order`` instance
855
should also be performed on the child ``Item`` instances attached to it. The
856
``delete-orphan`` cascade value additionally indicates that if an ``Item``
857
instance is no longer associated with an ``Order``, it should also be deleted.
858
The "all, delete-orphan" cascade argument allows a so-called *lifecycle*
859
relationship between an ``Order`` and an ``Item`` object.
861
The ``customer`` relationship specifies only the "save-update" cascade value,
862
indicating most operations will not be cascaded from a parent ``Order``
863
instance to a child ``User`` instance except for the
864
:func:`~sqlalchemy.orm.session.Session.add` operation. ``save-update`` cascade
865
indicates that an :func:`~sqlalchemy.orm.session.Session.add` on the parent
866
will cascade to all child items, and also that items added to a parent which
867
is already present in a session will also be added to that same session.
868
"save-update" cascade also cascades the *pending history* of a
869
relationship()-based attribute, meaning that objects which were removed from a
870
scalar or collection attribute whose changes have not yet been flushed are
871
also placed into the new session - this so that foreign key clear operations
872
and deletions will take place (new in 0.6).
874
Note that the ``delete-orphan`` cascade only functions for relationships where
875
the target object can have a single parent at a time, meaning it is only
876
appropriate for one-to-one or one-to-many relationships. For a
877
:func:`~sqlalchemy.orm.relationship` which establishes one-to-one via a local
878
foreign key, i.e. a many-to-one that stores only a single parent, or
879
one-to-one/one-to-many via a "secondary" (association) table, a warning will
880
be issued if ``delete-orphan`` is configured. To disable this warning, also
881
specify the ``single_parent=True`` flag on the relationship, which constrains
882
objects to allow attachment to only one parent at a time.
884
The default value for ``cascade`` on :func:`~sqlalchemy.orm.relationship` is
885
``save-update, merge``.
887
``save-update`` cascade also takes place on backrefs by default. This means
888
that, given a mapping such as this::
890
mapper(Order, order_table, properties={
891
'items' : relationship(Item, items_table, backref='order')
894
If an ``Order`` is already in the session, and is assigned to the ``order``
895
attribute of an ``Item``, the backref appends the ``Item`` to the ``orders``
896
collection of that ``Order``, resulting in the ``save-update`` cascade taking
911
This behavior can be disabled as of 0.6.5 using the ``cascade_backrefs`` flag::
913
mapper(Order, order_table, properties={
914
'items' : relationship(Item, items_table, backref='order',
915
cascade_backrefs=False)
918
So above, the assignment of ``i1.order = o1`` will append ``i1`` to the ``orders``
919
collection of ``o1``, but will not add ``i1`` to the session. You can of
920
course :func:`~.Session.add` ``i1`` to the session at a later point. This option
921
may be helpful for situations where an object needs to be kept out of a
922
session until it's construction is completed, but still needs to be given
923
associations to objects which are already persistent in the target session.
926
.. _unitofwork_transaction:
928
Managing Transactions
929
=====================
931
The :class:`~sqlalchemy.orm.session.Session` manages transactions across all
932
engines associated with it. As the :class:`~sqlalchemy.orm.session.Session`
933
receives requests to execute SQL statements using a particular
934
:class:`~sqlalchemy.engine.base.Engine` or
935
:class:`~sqlalchemy.engine.base.Connection`, it adds each individual
936
:class:`~sqlalchemy.engine.base.Engine` encountered to its transactional state
937
and maintains an open connection for each one (note that a simple application
938
normally has just one :class:`~sqlalchemy.engine.base.Engine`). At commit
939
time, all unflushed data is flushed, and each individual transaction is
940
committed. If the underlying databases support two-phase semantics, this may
941
be used by the Session as well if two-phase transactions are enabled.
943
Normal operation ends the transactional state using the
944
:func:`~sqlalchemy.orm.session.Session.rollback` or
945
:func:`~sqlalchemy.orm.session.Session.commit` methods. After either is
946
called, the :class:`~sqlalchemy.orm.session.Session` starts a new
949
Session = sessionmaker()
952
item1 = session.query(Item).get(1)
953
item2 = session.query(Item).get(2)
957
# commit- will immediately go into
958
# a new transaction on next use.
961
# rollback - will immediately go into
962
# a new transaction on next use.
965
A session which is configured with ``autocommit=True`` may be placed into a
966
transaction using :func:`~sqlalchemy.orm.session.Session.begin`. With an
967
``autocommit=True`` session that's been placed into a transaction using
968
:func:`~sqlalchemy.orm.session.Session.begin`, the session releases all
969
connection resources after a :func:`~sqlalchemy.orm.session.Session.commit` or
970
:func:`~sqlalchemy.orm.session.Session.rollback` and remains transaction-less
971
(with the exception of flushes) until the next
972
:func:`~sqlalchemy.orm.session.Session.begin` call::
974
Session = sessionmaker(autocommit=True)
978
item1 = session.query(Item).get(1)
979
item2 = session.query(Item).get(2)
987
The :func:`~sqlalchemy.orm.session.Session.begin` method also returns a
988
transactional token which is compatible with the Python 2.6 ``with``
991
Session = sessionmaker(autocommit=True)
993
with session.begin():
994
item1 = session.query(Item).get(1)
995
item2 = session.query(Item).get(2)
999
.. _session_begin_nested:
1004
SAVEPOINT transactions, if supported by the underlying engine, may be
1005
delineated using the :func:`~sqlalchemy.orm.session.Session.begin_nested`
1008
Session = sessionmaker()
1013
session.begin_nested() # establish a savepoint
1015
session.rollback() # rolls back u3, keeps u1 and u2
1017
session.commit() # commits u1 and u2
1019
:func:`~sqlalchemy.orm.session.Session.begin_nested` may be called any number
1020
of times, which will issue a new SAVEPOINT with a unique identifier for each
1021
call. For each :func:`~sqlalchemy.orm.session.Session.begin_nested` call, a
1022
corresponding :func:`~sqlalchemy.orm.session.Session.rollback` or
1023
:func:`~sqlalchemy.orm.session.Session.commit` must be issued.
1025
When :func:`~sqlalchemy.orm.session.Session.begin_nested` is called, a
1026
:func:`~sqlalchemy.orm.session.Session.flush` is unconditionally issued
1027
(regardless of the ``autoflush`` setting). This is so that when a
1028
:func:`~sqlalchemy.orm.session.Session.rollback` occurs, the full state of the
1029
session is expired, thus causing all subsequent attribute/instance access to
1030
reference the full state of the :class:`~sqlalchemy.orm.session.Session` right
1031
before :func:`~sqlalchemy.orm.session.Session.begin_nested` was called.
1033
.. _session_subtransactions:
1035
Using Subtransactions
1036
---------------------
1038
A subtransaction, as offered by the ``subtransactions=True`` flag of :meth:`.Session.begin`,
1039
is a non-transactional, delimiting construct that
1040
allows nesting of calls to :meth:`~.Session.begin` and :meth:`~.Session.commit`.
1041
It's purpose is to allow the construction of code that can function within a transaction
1042
both independently of any external code that starts a transaction,
1043
as well as within a block that has already demarcated a transaction. By "non-transactional", we
1044
mean that no actual transactional dialogue with the database is generated by this flag beyond that of
1045
a single call to :meth:`~.Session.begin`, regardless of how many times the method
1046
is called within a transaction.
1048
The subtransaction feature is in fact intrinsic to any call to :meth:`~.Session.flush`, which uses
1049
it internally to ensure that the series of flush steps are enclosed within a transaction,
1050
regardless of the setting of ``autocommit`` or the presence of an existing transactional context.
1051
However, explicit usage of the ``subtransactions=True`` flag is generally only useful with an
1052
application that uses the
1053
:class:`.Session` in "autocommit=True" mode, and calls :meth:`~.Session.begin` explicitly
1054
in order to demarcate transactions. For this reason the subtransaction feature is not
1055
commonly used in an explicit way, except for apps that integrate SQLAlchemy-level transaction control with
1056
the transaction control of another library or subsystem. For true, general purpose "nested"
1057
transactions, where a rollback affects only a portion of the work which has proceeded,
1058
savepoints should be used, documented in :ref:`session_begin_nested`.
1060
The feature is the ORM equivalent to the pattern described at :ref:`connections_nested_transactions`,
1061
where any number of functions can call :meth:`.Connection.begin` and :meth:`.Transaction.commit`
1062
as though they are the initiator of the transaction, but in fact may be participating
1063
in an already ongoing transaction.
1065
As is the case with the non-ORM :class:`.Transaction` object,
1066
calling :meth:`.Session.rollback` rolls back the **entire**
1067
transaction, which was initiated by the first call to
1068
:meth:`.Session.begin` (whether this call was explicit by the
1069
end user, or implicit in an ``autocommit=False`` scenario).
1070
However, the :class:`.Session` still considers itself to be in a
1071
"partially rolled back" state until :meth:`.Session.rollback` is
1072
called explicitly for each call that was made to
1073
:meth:`.Session.begin`, where "partially rolled back" means that
1074
no further SQL operations can proceed until each level
1075
of the transaction has been acounted for, unless the :meth:`~.Session.close` method
1076
is called which cancels all transactional markers. For a full exposition on
1077
the rationale for this,
1078
please see "`But why isn't the one automatic call to ROLLBACK
1079
enough ? Why must I ROLLBACK again?
1080
<http://www.sqlalchemy.org/trac/wiki/FAQ#ButwhyisnttheoneautomaticcalltoROLLBACKenoughWhymustIROLLBACKagain>`_".
1081
The general theme is that if subtransactions are used as intended, that is, as a means to nest multiple
1082
begin/commit pairs, the appropriate rollback calls naturally occur in any case, and allow the session's
1083
nesting of transactional pairs to function in a simple and predictable way
1084
without the need to guess as to what level is active.
1086
An example of ``subtransactions=True`` is nearly identical to
1087
that of the non-ORM technique. The nesting of transactions, as
1088
well as the natural presence of "rollback" for all transactions
1089
should an exception occur, is illustrated::
1091
# method_a starts a transaction and calls method_b
1092
def method_a(session):
1093
session.begin(subtransactions=True) # open a transaction. If there was
1094
# no previous call to begin(), this will
1095
# begin a real transaction (meaning, a
1096
# DBAPI connection is procured, which as
1097
# per the DBAPI specification is in a transactional
1098
# state ready to be committed or rolled back)
1101
session.commit() # transaction is committed here
1103
session.rollback() # rolls back the transaction
1106
# method_b also starts a transaction
1107
def method_b(connection):
1108
session.begin(subtransactions=True) # open a transaction - this
1109
# runs in the context of method_a()'s
1112
session.add(SomeObject('bat', 'lala'))
1113
session.commit() # transaction is not committed yet
1115
session.rollback() # rolls back the transaction, in this case
1116
# the one that was initiated in method_a().
1119
# create a Session and call method_a
1120
session = Session(autocommit=True)
1124
Since the :meth:`.Session.flush` method uses a subtransaction, a failed flush
1125
will always issue a rollback which then affects the state of the outermost transaction (unless a SAVEPOINT
1126
is in use). This forces the need to issue :meth:`~.Session.rollback` for the full operation
1127
before subsequent SQL operations can proceed.
1129
Enabling Two-Phase Commit
1130
-------------------------
1132
Finally, for MySQL, PostgreSQL, and soon Oracle as well, the session can be
1133
instructed to use two-phase commit semantics. This will coordinate the
1134
committing of transactions across databases so that the transaction is either
1135
committed or rolled back in all databases. You can also
1136
:func:`~sqlalchemy.orm.session.Session.prepare` the session for interacting
1137
with transactions not managed by SQLAlchemy. To use two phase transactions set
1138
the flag ``twophase=True`` on the session::
1140
engine1 = create_engine('postgresql://db1')
1141
engine2 = create_engine('postgresql://db2')
1143
Session = sessionmaker(twophase=True)
1145
# bind User operations to engine 1, Account operations to engine 2
1146
Session.configure(binds={User:engine1, Account:engine2})
1150
# .... work with accounts and users
1152
# commit. session will issue a flush to all DBs, and a prepare step to all DBs,
1153
# before committing both transactions
1156
Embedding SQL Insert/Update Expressions into a Flush
1157
=====================================================
1159
This feature allows the value of a database column to be set to a SQL
1160
expression instead of a literal value. It's especially useful for atomic
1161
updates, calling stored procedures, etc. All you do is assign an expression to
1164
class SomeClass(object):
1166
mapper(SomeClass, some_table)
1168
someobject = session.query(SomeClass).get(5)
1170
# set 'value' attribute to a SQL expression adding one
1171
someobject.value = some_table.c.value + 1
1173
# issues "UPDATE some_table SET value=value+1"
1176
This technique works both for INSERT and UPDATE statements. After the
1177
flush/commit operation, the ``value`` attribute on ``someobject`` above is
1178
expired, so that when next accessed the newly generated value will be loaded
1181
Using SQL Expressions with Sessions
1182
====================================
1184
SQL expressions and strings can be executed via the
1185
:class:`~sqlalchemy.orm.session.Session` within its transactional context.
1186
This is most easily accomplished using the
1187
:func:`~sqlalchemy.orm.session.Session.execute` method, which returns a
1188
:class:`~sqlalchemy.engine.base.ResultProxy` in the same manner as an
1189
:class:`~sqlalchemy.engine.base.Engine` or
1190
:class:`~sqlalchemy.engine.base.Connection`::
1192
Session = sessionmaker(bind=engine)
1195
# execute a string statement
1196
result = session.execute("select * from table where id=:id", {'id':7})
1198
# execute a SQL expression construct
1199
result = session.execute(select([mytable]).where(mytable.c.id==7))
1201
The current :class:`~sqlalchemy.engine.base.Connection` held by the
1202
:class:`~sqlalchemy.orm.session.Session` is accessible using the
1203
:func:`~sqlalchemy.orm.session.Session.connection` method::
1205
connection = session.connection()
1207
The examples above deal with a :class:`~sqlalchemy.orm.session.Session` that's
1208
bound to a single :class:`~sqlalchemy.engine.base.Engine` or
1209
:class:`~sqlalchemy.engine.base.Connection`. To execute statements using a
1210
:class:`~sqlalchemy.orm.session.Session` which is bound either to multiple
1211
engines, or none at all (i.e. relies upon bound metadata), both
1212
:func:`~sqlalchemy.orm.session.Session.execute` and
1213
:func:`~sqlalchemy.orm.session.Session.connection` accept a ``mapper`` keyword
1214
argument, which is passed a mapped class or
1215
:class:`~sqlalchemy.orm.mapper.Mapper` instance, which is used to locate the
1216
proper context for the desired engine::
1218
Session = sessionmaker()
1221
# need to specify mapper or class when executing
1222
result = session.execute("select * from table where id=:id", {'id':7}, mapper=MyMappedClass)
1224
result = session.execute(select([mytable], mytable.c.id==7), mapper=MyMappedClass)
1226
connection = session.connection(MyMappedClass)
1228
.. _session_external_transaction:
1230
Joining a Session into an External Transaction
1231
===============================================
1233
If a :class:`.Connection` is being used which is already in a transactional
1234
state (i.e. has a :class:`.Transaction` established), a :class:`.Session` can
1235
be made to participate within that transaction by just binding the
1236
:class:`.Session` to that :class:`.Connection`. The usual rationale for this
1237
is a test suite that allows ORM code to work freely with a :class:`.Session`,
1238
including the ability to call :meth:`.Session.commit`, where afterwards the
1239
entire database interaction is rolled back::
1241
from sqlalchemy.orm import sessionmaker
1242
from sqlalchemy import create_engine
1243
from unittest import TestCase
1245
# global application scope. create Session class, engine
1246
Session = sessionmaker()
1248
engine = create_engine('postgresql://...')
1250
class SomeTest(TestCase):
1252
# connect to the database
1253
self.connection = engine.connect()
1255
# begin a non-ORM transaction
1256
self.trans = connection.begin()
1258
# bind an individual Session to the connection
1259
self.session = Session(bind=self.connection)
1261
def test_something(self):
1262
# use the session in tests.
1264
self.session.add(Foo())
1265
self.session.commit()
1268
# rollback - everything that happened with the
1269
# Session above (including calls to commit())
1271
self.trans.rollback()
1272
self.session.close()
1274
Above, we issue :meth:`.Session.commit` as well as
1275
:meth:`.Transaction.rollback`. This is an example of where we take advantage
1276
of the :class:`.Connection` object's ability to maintain *subtransactions*, or
1277
nested begin/commit-or-rollback pairs where only the outermost begin/commit
1278
pair actually commits the transaction, or if the outermost block rolls back,
1279
everything is rolled back.
1281
The :class:`.Session` object and :func:`.sessionmaker` function
1282
================================================================
1284
.. autofunction:: sessionmaker
1286
.. autoclass:: sqlalchemy.orm.session.Session
1289
.. _unitofwork_contextual:
1291
Contextual/Thread-local Sessions
1292
=================================
1294
A common need in applications, particularly those built around web frameworks,
1295
is the ability to "share" a :class:`~sqlalchemy.orm.session.Session` object
1296
among disparate parts of an application, without needing to pass the object
1297
explicitly to all method and function calls. What you're really looking for is
1298
some kind of "global" session object, or at least "global" to all the parts of
1299
an application which are tasked with servicing the current request. For this
1300
pattern, SQLAlchemy provides the ability to enhance the
1301
:class:`~sqlalchemy.orm.session.Session` class generated by
1302
:func:`.sessionmaker` to provide auto-contextualizing support.
1303
This means that whenever you create a :class:`~sqlalchemy.orm.session.Session`
1304
instance with its constructor, you get an *existing*
1305
:class:`~sqlalchemy.orm.session.Session` object which is bound to some
1306
"context". By default, this context is the current thread. This feature is
1307
what previously was accomplished using the ``sessioncontext`` SQLAlchemy
1310
Creating a Thread-local Context
1311
-------------------------------
1313
The :func:`~sqlalchemy.orm.scoped_session` function wraps around the
1314
:func:`.sessionmaker` function, and produces an object which
1315
behaves the same as the :class:`~sqlalchemy.orm.session.Session` subclass
1316
returned by :func:`.sessionmaker`::
1318
from sqlalchemy.orm import scoped_session, sessionmaker
1319
Session = scoped_session(sessionmaker())
1321
However, when you instantiate this :class:`~sqlalchemy.orm.session.Session`
1322
"class", in reality the object is pulled from a threadlocal variable, or if it
1323
doesn't exist yet, it's created using the underlying class generated by
1324
:func:`.sessionmaker`::
1326
>>> # call Session() the first time. the new Session instance is created.
1327
>>> session = Session()
1329
>>> # later, in the same application thread, someone else calls Session()
1330
>>> session2 = Session()
1332
>>> # the two Session objects are *the same* object
1333
>>> session is session2
1336
Since the :class:`~sqlalchemy.orm.session.Session()` constructor now returns
1337
the same :class:`~sqlalchemy.orm.session.Session` object every time within the
1338
current thread, the object returned by :func:`~sqlalchemy.orm.scoped_session`
1339
also implements most of the :class:`~sqlalchemy.orm.session.Session` methods
1340
and properties at the "class" level, such that you don't even need to
1341
instantiate :class:`~sqlalchemy.orm.session.Session()`::
1343
# create some objects
1347
# save to the contextual session, without instantiating
1351
# view the "new" attribute
1352
assert u1 in Session.new
1357
The contextual session may be disposed of by calling ``Session.remove()``::
1359
# remove current contextual session
1362
After ``remove()`` is called, the next operation with the contextual session
1363
will start a new :class:`~sqlalchemy.orm.session.Session` for the current
1366
.. _session_lifespan:
1368
Lifespan of a Contextual Session
1369
--------------------------------
1371
A (really, really) common question is when does the contextual session get
1372
created, when does it get disposed ? We'll consider a typical lifespan as used
1373
in a web application::
1375
Web Server Web Framework User-defined Controller Call
1376
-------------- -------------- ------------------------------
1378
call controller -> # call Session(). this establishes a new,
1379
# contextual Session.
1382
# load some objects, save some changes
1383
objects = session.query(MyClass).all()
1385
# some other code calls Session, it's the
1386
# same contextual session as "sess"
1387
session2 = Session()
1391
# generate content to be returned
1392
return generate_content()
1396
The above example illustrates an explicit call to :meth:`.ScopedSession.remove`. This
1397
has the effect such that each web request starts fresh with a brand new
1398
session, and is the most definitive approach to closing out a request.
1400
It's not strictly necessary to remove the session at the end of the request -
1401
other options include calling :meth:`.Session.close`, :meth:`.Session.rollback`,
1402
:meth:`.Session.commit` at the end so that the existing session returns
1403
its connections to the pool and removes any existing transactional context.
1404
Doing nothing is an option too, if individual controller methods take responsibility
1405
for ensuring that no transactions remain open after a request ends.
1407
Contextual Session API
1408
-----------------------
1410
.. autofunction:: sqlalchemy.orm.scoped_session
1412
.. autoclass:: sqlalchemy.orm.scoping.ScopedSession
1415
.. autoclass:: sqlalchemy.util.ScopedRegistry
1418
.. autoclass:: sqlalchemy.util.ThreadLocalRegistry
1420
.. _session_partitioning:
1422
Partitioning Strategies
1423
=======================
1425
Vertical Partitioning
1426
---------------------
1428
Vertical partitioning places different kinds of objects, or different tables,
1429
across multiple databases::
1431
engine1 = create_engine('postgresql://db1')
1432
engine2 = create_engine('postgresql://db2')
1434
Session = sessionmaker(twophase=True)
1436
# bind User operations to engine 1, Account operations to engine 2
1437
Session.configure(binds={User:engine1, Account:engine2})
1441
Horizontal Partitioning
1442
-----------------------
1444
Horizontal partitioning partitions the rows of a single table (or a set of
1445
tables) across multiple databases.
1447
See the "sharding" example: :ref:`examples_sharding`.
1452
.. autofunction:: make_transient
1454
.. autofunction:: object_session
1456
Attribute and State Management Utilities
1457
========================================
1459
These functions are provided by the SQLAlchemy attribute
1460
instrumentation API to provide a detailed interface for dealing
1461
with instances, attribute values, and history. Some of them
1462
are useful when constructing event listener functions, such as
1463
those described in :ref:`events_orm_toplevel`.
1465
.. currentmodule:: sqlalchemy.orm.attributes
1467
.. autofunction:: del_attribute
1469
.. autofunction:: get_attribute
1471
.. autofunction:: get_history
1473
.. autofunction:: init_collection
1475
.. function:: instance_state
1477
Return the :class:`InstanceState` for a given object.
1479
.. autofunction:: is_instrumented
1481
.. function:: manager_of_class
1483
Return the :class:`ClassManager` for a given class.
1485
.. autofunction:: set_attribute
1487
.. autofunction:: set_committed_value
1489
.. autoclass:: History
1492
.. attribute:: sqlalchemy.orm.attributes.PASSIVE_NO_INITIALIZE
1494
Symbol indicating that loader callables should
1495
not be fired off, and a non-initialized attribute
1496
should remain that way.
1498
.. attribute:: sqlalchemy.orm.attributes.PASSIVE_NO_FETCH
1500
Symbol indicating that loader callables should not boe fired off.
1501
Non-initialized attributes should be initialized to an empty value.
1503
.. attribute:: sqlalchemy.orm.attributes.PASSIVE_OFF
1505
Symbol indicating that loader callables should be executed.