"""
def on_resurrect(self, target):
- """"""
+ """Receive an object instance as it is 'resurrected' from
+ garbage collection, which occurs when a "dirty" state falls
+ out of scope."""
class MapperEvents(event.Events):
"""Define events specific to mappings.
-
+
e.g.::
from sqlalchemy import event
- from sqlalchemy.orm import mapper
- # attach to a class
+ def my_before_insert_listener(mapper, connection, target):
+ # execute a stored procedure upon INSERT,
+ # apply the value to the row to be inserted
+ target.calculated_value = connection.scalar(
+ "select my_special_function(%d)"
+ % target.special_number)
+
+ # associate the listener function with SomeMappedClass,
+ # to execute during the "on_before_insert" hook
event.listen(my_before_insert_listener, 'on_before_insert', SomeMappedClass)
+ Available targets include mapped classes, instances of
+ :class:`.Mapper` (i.e. returned by :func:`.mapper`,
+ :func:`.class_mapper` and similar), as well as the
+ :class:`.Mapper` class and :func:`.mapper` function itself
+ for global event reception::
+
+ from sqlalchemy.orm import mapper
+
+ def some_listener(mapper, connection, target):
+ log.debug("Instance %s being inserted" % target)
+
# attach to all mappers
event.listen(some_listener, 'on_before_insert', mapper)
- Mapper event listeners are propagated to subclass (inheriting)
- mappers unconditionally.
+ Mapper events provide hooks into critical sections of the
+ mapper, including those related to object instrumentation,
+ object loading, and object persistence. In particular, the
+ persistence methods :meth:`~.MapperEvents.on_before_insert`,
+ and :meth:`~.MapperEvents.on_before_update` are popular
+ places to augment the state being persisted - however, these
+ methods operate with several significant restrictions. The
+ user is encouraged to evaluate the
+ :meth:`.SessionEvents.on_before_flush` and
+ :meth:`.SessionEvents.on_after_flush` methods as more
+ flexible and user-friendly hooks in which to apply
+ additional database state during a flush.
- Several modifiers are available to the listen() function.
+ When using :class:`.MapperEvents`, several modifiers are
+ available to the :func:`.event.listen` function.
:param propagate=False: When True, the event listener should
- be applied to all inheriting mappers as well.
- :param raw=False: When True, the "target" argument to the
- event, if applicable will be the :class:`.InstanceState` management
+ be applied to all inheriting mappers as well as the
+ mapper which is the target of this listener.
+ :param raw=False: When True, the "target" argument passed
+ to applicable event listener functions will be the
+ instance's :class:`.InstanceState` management
object, rather than the mapped instance itself.
:param retval=False: when True, the user-defined event function
must have a return value, the purpose of which is either to
control subsequent event propagation, or to otherwise alter
- the operation in progress by the mapper. Possible values
- here are:
+ the operation in progress by the mapper. Possible return
+ values are:
* ``sqlalchemy.orm.interfaces.EXT_CONTINUE`` - continue event
processing normally.
* ``sqlalchemy.orm.interfaces.EXT_STOP`` - cancel all subsequent
event handlers in the chain.
* other values - the return value specified by specific listeners,
- such as "translate_row" or "create_instance".
+ such as :meth:`~.MapperEvents.on_translate_row` or
+ :meth:`~.MapperEvents.on_create_instance`.
"""
This listener can generally only be applied to the :class:`.Mapper`
class overall.
+ :param mapper: the :class:`.Mapper` which is the target
+ of this event.
+ :param class\_: the mapped class.
+
"""
def on_translate_row(self, mapper, context, row):
It is called when the mapper first receives a row, before
the object identity or the instance itself has been derived
from that row. The given row may or may not be a
- ``RowProxy`` object - it will always be a dictionary-like
+ :class:`.RowProxy` object - it will always be a dictionary-like
object which contains mapped columns as keys. The
returned object should also be a dictionary-like object
which recognizes mapped columns as keys.
- If the ultimate return value is EXT_CONTINUE, the row
- is not translated.
+ :param mapper: the :class:`.Mapper` which is the target
+ of this event.
+ :param context: the :class:`.QueryContext`, which includes
+ a handle to the current :class:`.Query` in progress as well
+ as additional state information.
+ :param row: the result row being handled. This may be
+ an actual :class:`.RowProxy` or may be a dictionary containing
+ :class:`.Column` objects as keys.
+ :return: When configured with ``retval=True``, the function
+ should return a dictionary-like row object, or ``EXT_CONTINUE``,
+ indicating the original row should be used.
+
"""
EXT_CONTINUE to indicate normal object creation should take place.
This listener is typically registered with ``retval=True``.
- mapper
- The mapper doing the operation
-
- context
- The QueryContext generated from the Query.
-
- row
- The result row from the database
-
- class\_
- The class we are mapping.
-
- return value
- A new object instance, or EXT_CONTINUE
+ :param mapper: the :class:`.Mapper` which is the target
+ of this event.
+ :param context: the :class:`.QueryContext`, which includes
+ a handle to the current :class:`.Query` in progress as well
+ as additional state information.
+ :param row: the result row being handled. This may be
+ an actual :class:`.RowProxy` or may be a dictionary containing
+ :class:`.Column` objects as keys.
+ :param class\_: the mapped class.
+ :return: When configured with ``retval=True``, the return value
+ should be a newly created instance of the mapped class,
+ or ``EXT_CONTINUE`` indicating that default object construction
+ should take place.
"""
result, **flags):
"""Receive an object instance before that instance is appended
to a result list.
+
+ This is a rarely used hook which can be used to alter
+ the construction of a result list returned by :class:`.Query`.
+
+ :param mapper: the :class:`.Mapper` which is the target
+ of this event.
+ :param context: the :class:`.QueryContext`, which includes
+ a handle to the current :class:`.Query` in progress as well
+ as additional state information.
+ :param row: the result row being handled. This may be
+ an actual :class:`.RowProxy` or may be a dictionary containing
+ :class:`.Column` objects as keys.
+ :param target: the mapped instance being populated. If
+ the event is configured with ``raw=True``, this will
+ instead be the :class:`.InstanceState` state-management
+ object associated with the instance.
+ :param result: a list-like object where results are being
+ appended.
+ :param \**flags: Additional state information about the
+ current handling of the row.
+ :return: If this method is registered with ``retval=True``,
+ a return value of ``EXT_STOP`` will prevent the instance
+ from being appended to the given result list, whereas a
+ return value of ``EXT_CONTINUE`` will result in the default
+ behavior of appending the value to the result list.
- If this method is registered with ``retval=True``,
- the append operation can be replaced. If any value other than
- EXT_CONTINUE is returned, result appending will not proceed for
- this instance, giving this extension an opportunity to do the
- appending itself, if desired.
-
- mapper
- The mapper doing the operation.
-
- selectcontext
- The QueryContext generated from the Query.
-
- row
- The result row from the database.
-
- target
- The object instance to be appended to the result, or
- the InstanceState if registered with ``raw=True``.
-
- result
- List to which results are being appended.
-
- \**flags
- extra information about the row, same as criterion in
- ``create_row_processor()`` method of
- :class:`~sqlalchemy.orm.interfaces.MapperProperty`
"""
unloaded attributes to be populated. The method may be called
many times for a single instance, as multiple result rows are
used to populate eagerly loaded collections.
-
- If this listener is registered with ``retval=True`` and
- returns EXT_CONTINUE, instance population will
- proceed normally. If any other value or None is returned,
- instance population will not proceed, giving this extension an
- opportunity to populate the instance itself, if desired.
-
- As of 0.5, most usages of this hook are obsolete. For a
+
+ Most usages of this hook are obsolete. For a
generic "object has been newly created from a row" hook, use
- ``reconstruct_instance()``, or the ``@orm.reconstructor``
- decorator.
+ :meth:`.InstanceEvents.on_load`.
+
+ :param mapper: the :class:`.Mapper` which is the target
+ of this event.
+ :param context: the :class:`.QueryContext`, which includes
+ a handle to the current :class:`.Query` in progress as well
+ as additional state information.
+ :param row: the result row being handled. This may be
+ an actual :class:`.RowProxy` or may be a dictionary containing
+ :class:`.Column` objects as keys.
+ :param class\_: the mapped class.
+ :return: When configured with ``retval=True``, a return
+ value of ``EXT_STOP`` will bypass instance population by
+ the mapper. A value of ``EXT_CONTINUE`` indicates that
+ default instance population should take place.
"""
def on_before_insert(self, mapper, connection, target):
- """Receive an object instance before that instance is inserted
- into its table.
-
- This is a good place to set up primary key values and such
- that aren't handled otherwise.
-
- Column-based attributes can be modified within this method
- which will result in the new value being inserted. However
- *no* changes to the overall flush plan can be made, and
- manipulation of the ``Session`` will not have the desired effect.
- To manipulate the ``Session`` within an extension, use
- ``SessionExtension``.
+ """Receive an object instance before an INSERT statement
+ is emitted corresponding to that instance.
+
+ This event is used to modify local, non-object related
+ attributes on the instance before an INSERT occurs, as well
+ as to emit additional SQL statements on the given
+ connection.
+
+ The event is often called for a batch of objects of the
+ same class before their INSERT statements are emitted at
+ once in a later step. In the extremely rare case that
+ this is not desirable, the :func:`.mapper` can be
+ configured with ``batch=False``, which will cause
+ batches of instances to be broken up into individual
+ (and more poorly performing) event->persist->event
+ steps.
+
+ Handlers should **not** modify any attributes which are
+ mapped by :func:`.relationship`, nor should they attempt
+ to make any modifications to the :class:`.Session` in
+ this hook (including :meth:`.Session.add`,
+ :meth:`.Session.delete`, etc.) - such changes will not
+ take effect. For overall changes to the "flush plan",
+ use :meth:`.SessionEvents.before_flush`.
+
+ :param mapper: the :class:`.Mapper` which is the target
+ of this event.
+ :param connection: the :class:`.Connection` being used to
+ emit INSERT statements for this instance. This
+ provides a handle into the current transaction on the
+ target database specific to this instance.
+ :param target: the mapped instance being persisted. If
+ the event is configured with ``raw=True``, this will
+ instead be the :class:`.InstanceState` state-management
+ object associated with the instance.
+ :return: No return value is supported by this event.
"""
def on_after_insert(self, mapper, connection, target):
- """Receive an object instance after that instance is inserted.
+ """Receive an object instance after an INSERT statement
+ is emitted corresponding to that instance.
+
+ This event is used to modify in-Python-only
+ state on the instance after an INSERT occurs, as well
+ as to emit additional SQL statements on the given
+ connection.
+
+ The event is often called for a batch of objects of the
+ same class after their INSERT statements have been
+ emitted at once in a previous step. In the extremely
+ rare case that this is not desirable, the
+ :func:`.mapper` can be configured with ``batch=False``,
+ which will cause batches of instances to be broken up
+ into individual (and more poorly performing)
+ event->persist->event steps.
+
+ :param mapper: the :class:`.Mapper` which is the target
+ of this event.
+ :param connection: the :class:`.Connection` being used to
+ emit INSERT statements for this instance. This
+ provides a handle into the current transaction on the
+ target database specific to this instance.
+ :param target: the mapped instance being persisted. If
+ the event is configured with ``raw=True``, this will
+ instead be the :class:`.InstanceState` state-management
+ object associated with the instance.
+ :return: No return value is supported by this event.
"""
def on_before_update(self, mapper, connection, target):
- """Receive an object instance before that instance is updated.
-
- Note that this method is called for all instances that are marked as
- "dirty", even those which have no net changes to their column-based
- attributes. An object is marked as dirty when any of its column-based
- attributes have a "set attribute" operation called or when any of its
- collections are modified. If, at update time, no column-based
- attributes have any net changes, no UPDATE statement will be issued.
- This means that an instance being sent to before_update is *not* a
- guarantee that an UPDATE statement will be issued (although you can
- affect the outcome here).
+ """Receive an object instance before an UPDATE statement
+ is emitted corresponding to that instance.
+
+ This event is used to modify local, non-object related
+ attributes on the instance before an UPDATE occurs, as well
+ as to emit additional SQL statements on the given
+ connection.
+
+ This method is called for all instances that are
+ marked as "dirty", *even those which have no net changes
+ to their column-based attributes*. An object is marked
+ as dirty when any of its column-based attributes have a
+ "set attribute" operation called or when any of its
+ collections are modified. If, at update time, no
+ column-based attributes have any net changes, no UPDATE
+ statement will be issued. This means that an instance
+ being sent to :meth:`~.MapperEvents.on_before_update` is
+ *not* a guarantee that an UPDATE statement will be
+ issued, although you can affect the outcome here by
+ modifying attributes so that a net change in value does
+ exist.
To detect if the column-based attributes on the object have net
changes, and will therefore generate an UPDATE statement, use
``object_session(instance).is_modified(instance,
include_collections=False)``.
- Column-based attributes can be modified within this method
- which will result in the new value being updated. However
- *no* changes to the overall flush plan can be made, and
- manipulation of the ``Session`` will not have the desired effect.
- To manipulate the ``Session`` within an extension, use
- ``SessionExtension``.
-
+ The event is often called for a batch of objects of the
+ same class before their UPDATE statements are emitted at
+ once in a later step. In the extremely rare case that
+ this is not desirable, the :func:`.mapper` can be
+ configured with ``batch=False``, which will cause
+ batches of instances to be broken up into individual
+ (and more poorly performing) event->persist->event
+ steps.
+
+ Handlers should **not** modify any attributes which are
+ mapped by :func:`.relationship`, nor should they attempt
+ to make any modifications to the :class:`.Session` in
+ this hook (including :meth:`.Session.add`,
+ :meth:`.Session.delete`, etc.) - such changes will not
+ take effect. For overall changes to the "flush plan",
+ use :meth:`.SessionEvents.before_flush`.
+
+ :param mapper: the :class:`.Mapper` which is the target
+ of this event.
+ :param connection: the :class:`.Connection` being used to
+ emit UPDATE statements for this instance. This
+ provides a handle into the current transaction on the
+ target database specific to this instance.
+ :param target: the mapped instance being persisted. If
+ the event is configured with ``raw=True``, this will
+ instead be the :class:`.InstanceState` state-management
+ object associated with the instance.
+ :return: No return value is supported by this event.
"""
def on_after_update(self, mapper, connection, target):
- """Receive an object instance after that instance is updated.
+ """Receive an object instance after an UPDATE statement
+ is emitted corresponding to that instance.
+
+ This event is used to modify in-Python-only
+ state on the instance after an UPDATE occurs, as well
+ as to emit additional SQL statements on the given
+ connection.
+
+ This method is called for all instances that are
+ marked as "dirty", *even those which have no net changes
+ to their column-based attributes*, and for which
+ no UPDATE statement has proceeded. An object is marked
+ as dirty when any of its column-based attributes have a
+ "set attribute" operation called or when any of its
+ collections are modified. If, at update time, no
+ column-based attributes have any net changes, no UPDATE
+ statement will be issued. This means that an instance
+ being sent to :meth:`~.MapperEvents.on_after_update` is
+ *not* a guarantee that an UPDATE statement has been
+ issued.
+
+ To detect if the column-based attributes on the object have net
+ changes, and therefore resulted in an UPDATE statement, use
+ ``object_session(instance).is_modified(instance,
+ include_collections=False)``.
+
+ The event is often called for a batch of objects of the
+ same class after their UPDATE statements have been emitted at
+ once in a previous step. In the extremely rare case that
+ this is not desirable, the :func:`.mapper` can be
+ configured with ``batch=False``, which will cause
+ batches of instances to be broken up into individual
+ (and more poorly performing) event->persist->event
+ steps.
+
+ :param mapper: the :class:`.Mapper` which is the target
+ of this event.
+ :param connection: the :class:`.Connection` being used to
+ emit UPDATE statements for this instance. This
+ provides a handle into the current transaction on the
+ target database specific to this instance.
+ :param target: the mapped instance being persisted. If
+ the event is configured with ``raw=True``, this will
+ instead be the :class:`.InstanceState` state-management
+ object associated with the instance.
+ :return: No return value is supported by this event.
"""
def on_before_delete(self, mapper, connection, target):
- """Receive an object instance before that instance is deleted.
-
- Note that *no* changes to the overall flush plan can be made
- here; and manipulation of the ``Session`` will not have the
- desired effect. To manipulate the ``Session`` within an
- extension, use ``SessionExtension``.
-
+ """Receive an object instance before a DELETE statement
+ is emitted corresponding to that instance.
+
+ This event is used to emit additional SQL statements on
+ the given connection as well as to perform application
+ specific bookkeeping related to a deletion event.
+
+ The event is often called for a batch of objects of the
+ same class before their DELETE statements are emitted at
+ once in a later step.
+
+ Handlers should **not** modify any attributes which are
+ mapped by :func:`.relationship`, nor should they attempt
+ to make any modifications to the :class:`.Session` in
+ this hook (including :meth:`.Session.add`,
+ :meth:`.Session.delete`, etc.) - such changes will not
+ take effect. For overall changes to the "flush plan",
+ use :meth:`.SessionEvents.before_flush`.
+
+ :param mapper: the :class:`.Mapper` which is the target
+ of this event.
+ :param connection: the :class:`.Connection` being used to
+ emit DELETE statements for this instance. This
+ provides a handle into the current transaction on the
+ target database specific to this instance.
+ :param target: the mapped instance being deleted. If
+ the event is configured with ``raw=True``, this will
+ instead be the :class:`.InstanceState` state-management
+ object associated with the instance.
+ :return: No return value is supported by this event.
+
"""
def on_after_delete(self, mapper, connection, target):
- """Receive an object instance after that instance is deleted.
-
+ """Receive an object instance after a DELETE statement
+ has been emitted corresponding to that instance.
+
+ This event is used to emit additional SQL statements on
+ the given connection as well as to perform application
+ specific bookkeeping related to a deletion event.
+
+ The event is often called for a batch of objects of the
+ same class after their DELETE statements have been emitted at
+ once in a previous step.
+
+ :param mapper: the :class:`.Mapper` which is the target
+ of this event.
+ :param connection: the :class:`.Connection` being used to
+ emit DELETE statements for this instance. This
+ provides a handle into the current transaction on the
+ target database specific to this instance.
+ :param target: the mapped instance being deleted. If
+ the event is configured with ``raw=True``, this will
+ instead be the :class:`.InstanceState` state-management
+ object associated with the instance.
+ :return: No return value is supported by this event.
+
"""
@classmethod
event.listen(my_set_listener, 'on_set',
MyClass.somescalar, retval=True)
- Several modifiers are available to the listen() function.
+ Several modifiers are available to the :func:`~event.listen` function.
:param active_history=False: When True, indicates that the
"on_set" event would like to receive the "old" value
replaces it.
:param initiator: the attribute implementation object
which initiated this event.
-
+ :return: if the event was registered with ``retval=True``,
+ the given value, or a new effective value, should be returned.
+
"""
def on_remove(self, target, value, initiator):
:param value: the value being removed.
:param initiator: the attribute implementation object
which initiated this event.
-
+ :return: No return value is defined for this event.
"""
def on_set(self, target, value, oldvalue, initiator):
or expired.
:param initiator: the attribute implementation object
which initiated this event.
+ :return: if the event was registered with ``retval=True``,
+ the given value, or a new effective value, should be returned.
"""