diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2015-08-28 16:06:03 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2015-09-02 11:58:59 -0400 |
commit | 8be93c23ee566de7cefd7d1b8ef044324132a70f (patch) | |
tree | 8d500663410ea10f40585c049df96e357f11d8b5 | |
parent | 956907a4b15f6dcc492582a7ad03706ff62d96fb (diff) | |
download | sqlalchemy-ticket_2677_pre.tar.gz |
- add new documentation that applies to all modern SQLA versions,ticket_2677_pre
detailing ORM event recipes across the board.
-rw-r--r-- | doc/build/core/events.rst | 4 | ||||
-rw-r--r-- | doc/build/orm/events.rst | 10 | ||||
-rw-r--r-- | doc/build/orm/examples.rst | 2 | ||||
-rw-r--r-- | doc/build/orm/session.rst | 1 | ||||
-rw-r--r-- | doc/build/orm/session_events.rst | 218 | ||||
-rw-r--r-- | doc/build/orm/session_state_management.rst | 31 | ||||
-rw-r--r-- | doc/build/orm/session_transaction.rst | 7 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/events.py | 223 |
8 files changed, 339 insertions, 157 deletions
diff --git a/doc/build/core/events.rst b/doc/build/core/events.rst index d19b910b1..451cb9460 100644 --- a/doc/build/core/events.rst +++ b/doc/build/core/events.rst @@ -11,10 +11,6 @@ ORM events are described in :ref:`orm_event_toplevel`. .. autoclass:: sqlalchemy.event.base.Events :members: -.. versionadded:: 0.7 - The event system supersedes the previous system of "extension", "listener", - and "proxy" classes. - Connection Pool Events ----------------------- diff --git a/doc/build/orm/events.rst b/doc/build/orm/events.rst index e9673bed0..470a9386b 100644 --- a/doc/build/orm/events.rst +++ b/doc/build/orm/events.rst @@ -5,12 +5,10 @@ ORM Events The ORM includes a wide variety of hooks available for subscription. -.. versionadded:: 0.7 - The event supersedes the previous system of "extension" classes. - -For an introduction to the event API, see :ref:`event_toplevel`. Non-ORM events -such as those regarding connections and low-level statement execution are described in -:ref:`core_event_toplevel`. +For an introduction to the most commonly used ORM events, see the section +:ref:`session_events_toplevel`. The event system in general is discussed +at :ref:`event_toplevel`. Non-ORM events such as those regarding connections +and low-level statement execution are described in :ref:`core_event_toplevel`. Attribute Events ---------------- diff --git a/doc/build/orm/examples.rst b/doc/build/orm/examples.rst index 4db7c00dc..25d243022 100644 --- a/doc/build/orm/examples.rst +++ b/doc/build/orm/examples.rst @@ -93,6 +93,8 @@ Versioning with a History Table .. automodule:: examples.versioned_history +.. _examples_versioned_rows: + Versioning using Temporal Rows ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/doc/build/orm/session.rst b/doc/build/orm/session.rst index 624ee9f75..79ea70137 100644 --- a/doc/build/orm/session.rst +++ b/doc/build/orm/session.rst @@ -20,6 +20,7 @@ configured, the primary usage interface for persistence operations is the session_transaction persistence_techniques contextual + session_events session_api diff --git a/doc/build/orm/session_events.rst b/doc/build/orm/session_events.rst new file mode 100644 index 000000000..231311aa0 --- /dev/null +++ b/doc/build/orm/session_events.rst @@ -0,0 +1,218 @@ +.. _session_events_toplevel: + +Tracking Object and Session Changes with Events +=============================================== + +SQLAlchemy features an extensive :ref:`Event Listening <event_toplevel>` +system used throughout the Core and ORM. Within the ORM, there are a +wide variety of event listener hooks, which are documented at an API +level at :ref:`orm_event_toplevel`. This collection of events has +grown over the years to include lots of very useful new events as well +as some older events that aren't as relevant as they once were. This +section will attempt to introduce the major event hooks and when they +might be used. + +.. _session_persistence_events: + +Persistence Events +------------------ + +Probably the most widely used series of events are the "persistence" events, +which correspond to the :ref:`flush process<session_flushing>`. +The flush is where all the decisions are made about pending changes to +objects and are then emitted out to the database in the form of INSERT, +UPDATE, and DELETE staetments. + +``before_flush()`` +^^^^^^^^^^^^^^^^^^ + +The :meth:`.SessionEvents.before_flush` hook is by far the most generally +useful event to use when an application wants to ensure that +additional persistence changes to the database are made when a flush proceeds. +Use :meth:`.SessionEvents.before_flush` in order to operate +upon objects to validate their state as well as to compose additional objects +and references before they are persisted. Within this event, +it is **safe to manipulate the Session's state**, that is, new objects +can be attached to it, objects can be deleted, and indivual attributes +on objects can be changed freely, and these changes will be pulled into +the flush process when the event hook completes. + +The typical :meth:`.SessionEvents.before_flush` hook will be tasked with +scanning the collections :attr:`.Session.new`, :attr:`.Session.dirty` and +:attr:`.Session.deleted` in order to look for objects +where something will be happening. + +For illustrations of :meth:`.SessionEvents.before_flush, see +examples such as :ref:`examples_versioned_history` and +:ref:`examples_versioned_rows`. + +``after_flush()`` +^^^^^^^^^^^^^^^^^ + +The :meth:`.SessionEvents.after_flush` hook is called after the SQL has been +emitted for a flush process, but **before* the state of the objects that +were flushed has been altered. That is, you can still inspect +the :attr:`.Session.new`, :attr:`.Session.dirty` and +:attr:`.Session.deleted` collections to see what was just flushed, and +you can also use history tracking features like the ones provided +by :class:`.AttributeState` to see what changes were just persisted. +In the :meth:`.SessionEvents.after_flush` event, additional SQL can be emitted +to the database based on what's observed to have changed. + +``after_flush_postexec()`` +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:meth:`.SessionEvents.after_flush_postexec` is called soon after +:meth:`.SessionEvents.after_flush`, but is invoked **after** the state of +the objects has been modified to account for the flush that just took place. +The :attr:`.Session.new`, :attr:`.Session.dirty` and +:attr:`.Session.deleted` collections are normally completely empty here. +Use :meth:`.SessionEvents.after_flush_postexec` to inspect the identity map +for finalized objects and possibly emit additional SQL. In this hook, +there is the ability to make new changes on objects, which means the +:class:`.Session` will again go into a "dirty" state; the mechanics of the +:class:`.Session` here will cause it to flush **again** if new changes +are detected in this hook. A counter ensures that an endless loop in this +regard is stopped after 100 iterations, in the case that an +:meth:`.SessionEvents.after_flush_postexec` +hook continually adds new state to be flushed each time it is called. + +.. _session_persistence_mapper: + +Mapper-level Events +^^^^^^^^^^^^^^^^^^^ + +In addition to the flush-level hooks, there is also a suite of hooks +that are more fine-grained, in that they are called on a per-object +basis and are broken out based on INSERT, UPDATE or DELETE. These +are the mapper persistence hooks, and they too are very popular, +however these events need to be approached more cautiously, as they +proceed within the context of the flush process that is already +ongoing; many operations are not safe to proceed here. + +The events are: + +* :meth:`.MapperEvents.before_insert` +* :meth:`.MapperEvents.after_insert` +* :meth:`.MapperEvents.before_update` +* :meth:`.MapperEvents.after_update` +* :meth:`.MapperEvents.before_delete` +* :meth:`.MapperEvents.after_delete` + +Each event is passed the :class:`.Mapper`, +the mapped object itself, and the :class:`.Connection` which is being +used to emit an INSERT, UPDATE or DELETE statement. The appeal of these +events is clear, in that if an application wants to tie some activity to +when a specific type of object is persisted with an INSERT, the hook is +very specific; unlike the :meth:`.SessionEvents.before_flush` event, +there's no need to search through collections like :attr:`.Session.new` +in order to find targets. However, the flush plan which +represents the full list of every single INSERT, UPDATE, DELETE statement +to be emitted has *already been decided* when these events are called, +and no changes may be made at this stage. Therefore the only changes that are +even possible to the given objects are upon attributes **local** to the +object's row. Any other change to the object or other objects will +impact the state of the :class:`.Session`, which will fail to function +properly. + +Operations that are not supported within these mapper-level persistence +events include: + +* :meth:`.Session.add` +* :meth:`.Session.delete` +* Mapped collection append, add, remove, delete, discard, etc. +* Mapped relationship attribute set/del events, + i.e. ``someobject.related = someotherobject`` + +The reason the :class:`.Connection` is passed is that it is encouraged that +**simple SQL operations take place here**, directly on the :class:`.Connection`, +such as incrementing counters or inserting extra rows within log tables. +When dealing with the :class:`.Connection`, it is expected that Core-level +SQL operations will be used; e.g. those described in :ref:`sqlexpression_toplevel`. + +There are also many per-object operations that don't need to be handled +within a flush event at all. The most common alternative is to simply +establish additional state along with an object inside its ``__init__()`` +method, such as creating additional objects that are to be associated with +the new object. Using validators as described in :ref:`simple_validators` is +another approach; these functions can intercept changes to attributes and +establish additional state changes on the target object in response to the +attribute change. With both of these approaches, the object is in +the correct state before it ever gets to the flush step. + +.. _session_lifecycle_events: + +Object Lifecycle Events +----------------------- + +Another use case for events is to track the lifecycle of objects. This +refers to the states first introduced at :ref:`session_object_states`. + +As of SQLAlchemy 1.0, there is no direct event interface for tracking of +these states. Events that can be used at the moment to track the state of +objects include: + +* :meth:`.InstanceEvents.init` + +* :meth:`.InstanceEvents.load` + +* :meth:`.SessionEvents.before_attach` + +* :meth:`.SessionEvents.after_attach` + +* :meth:`.SessionEvents.before_flush` - by scanning the session's collections + +* :meth:`.SessionEvents.after_flush` - by scanning the session's collections + +SQLAlchemy 1.1 will introduce a comprehensive event system to track +the object persistence states fully and unambiguously. + +.. _session_transaction_events: + +Transaction Events +------------------ + +Transaction events allow an application to be notifed when transaction +boundaries occur at the :class:`.Session` level as well as when the +:class:`.Session` changes the transactional state on :class:`.Connection` +objects. + +* :meth:`.SessionEvents.after_transaction_create`, + :meth:`.SessionEvents.after_transaction_end` - these events track the + logical transaction scopes of the :class:`.Session` in a way that is + not specific to individual database connections. These events are + intended to help with integration of transaction-tracking systems such as + ``zope.sqlalchemy``. Use these + events when the application needs to align some external scope with the + transactional scope of the :class:`.Session`. These hooks mirror + the "nested" transactional behavior of the :class:`.Session`, in that they + track logical "subtransactions" as well as "nested" (e.g. SAVEPOINT) + transactions. + +* :meth:`.SessionEvents.before_commit`, :meth:`.SessionEvents.after_commit`, + :meth:`.SessionEvents.after_begin`, + :meth:`.SessionEvents.after_rollback`, :meth:`.SessionEvents.after_soft_rollback` - + These events allow tracking of transaction events from the perspective + of database connections. :meth:`.SessionEvents.after_begin` in particular + is a per-connection event; a :class:`.Session` that maintains more than + one connection will emit this event for each connection individually + as those connections become used within the current transaction. + The rollback and commit events then refer to when the DBAPI connections + themselves have received rollback or commit instructions directly. + +Attribute Change Events +----------------------- + +The attribute change events allow interception of when specific attributes +on an object are modified. These events include :meth:`.AttributeEvents.set`, +:meth:`.AttributeEvents.append`, and :meth:`.AttributeEvents.remove`. These +events are extremely useful, particularly for per-object validation operations; +however, it is often much more convenient to use a "validator" hook, which +uses these hooks behind the scenes; see :ref:`simple_validators` for +background on this. The attribute events are also behind the mechanics +of backreferences. An example illustrating use of attribute events +is in :ref:`examples_instrumentation`. + + + + diff --git a/doc/build/orm/session_state_management.rst b/doc/build/orm/session_state_management.rst index 1a8bb3dee..18673fde1 100644 --- a/doc/build/orm/session_state_management.rst +++ b/doc/build/orm/session_state_management.rst @@ -23,11 +23,25 @@ It's helpful to know the states which an instance can have within a session: existing instances (or moving persistent instances from other sessions into your local session). -* **Detached** - an instance which has a record in the database, but is not in - any session. There's nothing wrong with this, and you can use objects - normally when they're detached, **except** they will not be able to issue - any SQL in order to load collections or attributes which are not yet loaded, - or were marked as "expired". + .. note:: + + An object that is marked as deleted, e.g. via the + :meth:`.Session.delete` method, is still considered persistent. The + object remains in the identity map until the flush proceeds and a DELETE + state is emitted, at which point the object moves to the state that is + for most practical purposes "detached" - after the session's transaction + is committed, the object becomes fully detached. SQLAlchemy 1.1 will + introduce a new object state called "deleted" which represents + this "deleted but not quite detached" state explicitly. + +* **Detached** - an instance which corresponds, or previously corresponded, + to a record in the database, but is not currently in any session. + The detached object will contain a database identity marker, however + because it is not associated with a session, it is unknown whether or not + this database identity actually exists in a target database. Detached + objects are safe to use normally, except that they have no ability to + load unloaded attributes or attributes that were previously marked + as "expired". Knowing these states is important, since the :class:`.Session` tries to be strict about ambiguous @@ -55,6 +69,8 @@ the :func:`.inspect` system:: :attr:`.InstanceState.detached` +.. _session_attributes: + Session Attributes ------------------ @@ -121,8 +137,9 @@ referenced. or into lists or sets for the span of time that they need to remain referenced. These collections can be associated with a :class:`.Session`, if desired, by placing them into the :attr:`.Session.info` dictionary. Events such - as the :meth:`.SessionEvents.after_attach` event may also be of use for - intercepting objects as they are associated with a :class:`.Session`. + as the :meth:`.SessionEvents.after_attach` and :meth:`.MapperEvents.load` + event may also be of use for intercepting objects as they are associated + with a :class:`.Session`. .. _unitofwork_merging: diff --git a/doc/build/orm/session_transaction.rst b/doc/build/orm/session_transaction.rst index bca3e944f..e197eb715 100644 --- a/doc/build/orm/session_transaction.rst +++ b/doc/build/orm/session_transaction.rst @@ -414,6 +414,12 @@ on the target connection, a warning is emitted:: :paramref:`.Session.connection.execution_options` parameter to :meth:`.Session.connection`. +Tracking Transaction State with Events +-------------------------------------- + +See the section :ref:`session_transaction_events` for an overview +of the available event hooks for session transaction state changes. + .. _session_external_transaction: Joining a Session into an External Transaction (such as for test suites) @@ -513,3 +519,4 @@ everything is rolled back. session.begin_nested() # ... the tearDown() method stays the same + diff --git a/lib/sqlalchemy/orm/events.py b/lib/sqlalchemy/orm/events.py index 6d4aa039b..29bdbaa8c 100644 --- a/lib/sqlalchemy/orm/events.py +++ b/lib/sqlalchemy/orm/events.py @@ -825,30 +825,14 @@ class MapperEvents(event.Events): steps. .. warning:: - Mapper-level flush events are designed to operate **on attributes - local to the immediate object being handled - and via SQL operations with the given** - :class:`.Connection` **only.** Handlers here should **not** make - alterations to the state of the :class:`.Session` overall, and - in general should not affect any :func:`.relationship` -mapped - attributes, as session cascade rules will not function properly, - nor is it always known if the related class has already been - handled. Operations that **are not supported in mapper - events** include: - - * :meth:`.Session.add` - * :meth:`.Session.delete` - * Mapped collection append, add, remove, delete, discard, etc. - * Mapped relationship attribute set/del events, - i.e. ``someobject.related = someotherobject`` - - Operations which manipulate the state of the object - relative to other objects are better handled: - - * In the ``__init__()`` method of the mapped object itself, or - another method designed to establish some particular state. - * In a ``@validates`` handler, see :ref:`simple_validators` - * Within the :meth:`.SessionEvents.before_flush` event. + + Mapper-level flush events only allow **very limited operations**, + on attributes local to the row being operated upon only, + as well as allowing any SQL to be emitted on the given + :class:`.Connection`. **Please read fully** the notes + at :ref:`session_persistence_mapper` for guidelines on using + these methods; generally, the :meth:`.SessionEvents.before_flush` + method should be preferred for general on-flush changes. :param mapper: the :class:`.Mapper` which is the target of this event. @@ -862,6 +846,10 @@ class MapperEvents(event.Events): object associated with the instance. :return: No return value is supported by this event. + .. seealso:: + + :ref:`session_persistence_events` + """ def after_insert(self, mapper, connection, target): @@ -883,30 +871,14 @@ class MapperEvents(event.Events): event->persist->event steps. .. warning:: - Mapper-level flush events are designed to operate **on attributes - local to the immediate object being handled - and via SQL operations with the given** - :class:`.Connection` **only.** Handlers here should **not** make - alterations to the state of the :class:`.Session` overall, and in - general should not affect any :func:`.relationship` -mapped - attributes, as session cascade rules will not function properly, - nor is it always known if the related class has already been - handled. Operations that **are not supported in mapper - events** include: - - * :meth:`.Session.add` - * :meth:`.Session.delete` - * Mapped collection append, add, remove, delete, discard, etc. - * Mapped relationship attribute set/del events, - i.e. ``someobject.related = someotherobject`` - - Operations which manipulate the state of the object - relative to other objects are better handled: - - * In the ``__init__()`` method of the mapped object itself, - or another method designed to establish some particular state. - * In a ``@validates`` handler, see :ref:`simple_validators` - * Within the :meth:`.SessionEvents.before_flush` event. + + Mapper-level flush events only allow **very limited operations**, + on attributes local to the row being operated upon only, + as well as allowing any SQL to be emitted on the given + :class:`.Connection`. **Please read fully** the notes + at :ref:`session_persistence_mapper` for guidelines on using + these methods; generally, the :meth:`.SessionEvents.before_flush` + method should be preferred for general on-flush changes. :param mapper: the :class:`.Mapper` which is the target of this event. @@ -920,6 +892,10 @@ class MapperEvents(event.Events): object associated with the instance. :return: No return value is supported by this event. + .. seealso:: + + :ref:`session_persistence_events` + """ def before_update(self, mapper, connection, target): @@ -960,29 +936,14 @@ class MapperEvents(event.Events): steps. .. warning:: - Mapper-level flush events are designed to operate **on attributes - local to the immediate object being handled - and via SQL operations with the given** :class:`.Connection` - **only.** Handlers here should **not** make alterations to the - state of the :class:`.Session` overall, and in general should not - affect any :func:`.relationship` -mapped attributes, as - session cascade rules will not function properly, nor is it - always known if the related class has already been handled. - Operations that **are not supported in mapper events** include: - - * :meth:`.Session.add` - * :meth:`.Session.delete` - * Mapped collection append, add, remove, delete, discard, etc. - * Mapped relationship attribute set/del events, - i.e. ``someobject.related = someotherobject`` - - Operations which manipulate the state of the object - relative to other objects are better handled: - - * In the ``__init__()`` method of the mapped object itself, - or another method designed to establish some particular state. - * In a ``@validates`` handler, see :ref:`simple_validators` - * Within the :meth:`.SessionEvents.before_flush` event. + + Mapper-level flush events only allow **very limited operations**, + on attributes local to the row being operated upon only, + as well as allowing any SQL to be emitted on the given + :class:`.Connection`. **Please read fully** the notes + at :ref:`session_persistence_mapper` for guidelines on using + these methods; generally, the :meth:`.SessionEvents.before_flush` + method should be preferred for general on-flush changes. :param mapper: the :class:`.Mapper` which is the target of this event. @@ -995,6 +956,11 @@ class MapperEvents(event.Events): instead be the :class:`.InstanceState` state-management object associated with the instance. :return: No return value is supported by this event. + + .. seealso:: + + :ref:`session_persistence_events` + """ def after_update(self, mapper, connection, target): @@ -1034,29 +1000,14 @@ class MapperEvents(event.Events): steps. .. warning:: - Mapper-level flush events are designed to operate **on attributes - local to the immediate object being handled - and via SQL operations with the given** :class:`.Connection` - **only.** Handlers here should **not** make alterations to the - state of the :class:`.Session` overall, and in general should not - affect any :func:`.relationship` -mapped attributes, as - session cascade rules will not function properly, nor is it - always known if the related class has already been handled. - Operations that **are not supported in mapper events** include: - - * :meth:`.Session.add` - * :meth:`.Session.delete` - * Mapped collection append, add, remove, delete, discard, etc. - * Mapped relationship attribute set/del events, - i.e. ``someobject.related = someotherobject`` - - Operations which manipulate the state of the object - relative to other objects are better handled: - - * In the ``__init__()`` method of the mapped object itself, - or another method designed to establish some particular state. - * In a ``@validates`` handler, see :ref:`simple_validators` - * Within the :meth:`.SessionEvents.before_flush` event. + + Mapper-level flush events only allow **very limited operations**, + on attributes local to the row being operated upon only, + as well as allowing any SQL to be emitted on the given + :class:`.Connection`. **Please read fully** the notes + at :ref:`session_persistence_mapper` for guidelines on using + these methods; generally, the :meth:`.SessionEvents.before_flush` + method should be preferred for general on-flush changes. :param mapper: the :class:`.Mapper` which is the target of this event. @@ -1070,6 +1021,10 @@ class MapperEvents(event.Events): object associated with the instance. :return: No return value is supported by this event. + .. seealso:: + + :ref:`session_persistence_events` + """ def before_delete(self, mapper, connection, target): @@ -1085,29 +1040,14 @@ class MapperEvents(event.Events): once in a later step. .. warning:: - Mapper-level flush events are designed to operate **on attributes - local to the immediate object being handled - and via SQL operations with the given** :class:`.Connection` - **only.** Handlers here should **not** make alterations to the - state of the :class:`.Session` overall, and in general should not - affect any :func:`.relationship` -mapped attributes, as - session cascade rules will not function properly, nor is it - always known if the related class has already been handled. - Operations that **are not supported in mapper events** include: - - * :meth:`.Session.add` - * :meth:`.Session.delete` - * Mapped collection append, add, remove, delete, discard, etc. - * Mapped relationship attribute set/del events, - i.e. ``someobject.related = someotherobject`` - - Operations which manipulate the state of the object - relative to other objects are better handled: - - * In the ``__init__()`` method of the mapped object itself, - or another method designed to establish some particular state. - * In a ``@validates`` handler, see :ref:`simple_validators` - * Within the :meth:`.SessionEvents.before_flush` event. + + Mapper-level flush events only allow **very limited operations**, + on attributes local to the row being operated upon only, + as well as allowing any SQL to be emitted on the given + :class:`.Connection`. **Please read fully** the notes + at :ref:`session_persistence_mapper` for guidelines on using + these methods; generally, the :meth:`.SessionEvents.before_flush` + method should be preferred for general on-flush changes. :param mapper: the :class:`.Mapper` which is the target of this event. @@ -1121,6 +1061,10 @@ class MapperEvents(event.Events): object associated with the instance. :return: No return value is supported by this event. + .. seealso:: + + :ref:`session_persistence_events` + """ def after_delete(self, mapper, connection, target): @@ -1136,29 +1080,14 @@ class MapperEvents(event.Events): once in a previous step. .. warning:: - Mapper-level flush events are designed to operate **on attributes - local to the immediate object being handled - and via SQL operations with the given** :class:`.Connection` - **only.** Handlers here should **not** make alterations to the - state of the :class:`.Session` overall, and in general should not - affect any :func:`.relationship` -mapped attributes, as - session cascade rules will not function properly, nor is it - always known if the related class has already been handled. - Operations that **are not supported in mapper events** include: - - * :meth:`.Session.add` - * :meth:`.Session.delete` - * Mapped collection append, add, remove, delete, discard, etc. - * Mapped relationship attribute set/del events, - i.e. ``someobject.related = someotherobject`` - - Operations which manipulate the state of the object - relative to other objects are better handled: - - * In the ``__init__()`` method of the mapped object itself, - or another method designed to establish some particular state. - * In a ``@validates`` handler, see :ref:`simple_validators` - * Within the :meth:`.SessionEvents.before_flush` event. + + Mapper-level flush events only allow **very limited operations**, + on attributes local to the row being operated upon only, + as well as allowing any SQL to be emitted on the given + :class:`.Connection`. **Please read fully** the notes + at :ref:`session_persistence_mapper` for guidelines on using + these methods; generally, the :meth:`.SessionEvents.before_flush` + method should be preferred for general on-flush changes. :param mapper: the :class:`.Mapper` which is the target of this event. @@ -1172,6 +1101,10 @@ class MapperEvents(event.Events): object associated with the instance. :return: No return value is supported by this event. + .. seealso:: + + :ref:`session_persistence_events` + """ @@ -1412,6 +1345,8 @@ class SessionEvents(event.Events): :meth:`~.SessionEvents.after_flush_postexec` + :ref:`session_persistence_events` + """ def after_flush(self, session, flush_context): @@ -1432,6 +1367,8 @@ class SessionEvents(event.Events): :meth:`~.SessionEvents.after_flush_postexec` + :ref:`session_persistence_events` + """ def after_flush_postexec(self, session, flush_context): @@ -1454,6 +1391,8 @@ class SessionEvents(event.Events): :meth:`~.SessionEvents.after_flush` + :ref:`session_persistence_events` + """ def after_begin(self, session, transaction, connection): @@ -1491,6 +1430,8 @@ class SessionEvents(event.Events): :meth:`~.SessionEvents.after_attach` + :ref:`session_lifecycle_events` + """ def after_attach(self, session, instance): @@ -1513,6 +1454,8 @@ class SessionEvents(event.Events): :meth:`~.SessionEvents.before_attach` + :ref:`session_lifecycle_events` + """ @event._legacy_signature("0.9", |