class AttributeEvents(event.Events):
Define events for object attributes.
These are typically defined on the class-bound descriptor for the target class.
e.g.:
from sqlalchemy import event @event.listens_for(MyClass.collection, 'append', propagate=True) def my_append_listener(target, value, initiator): print("received append event for target: %s" % target)
Listeners have the option to return a possibly modified version of the
value, when the :paramref:`.AttributeEvents.retval` flag is passed to
.event.listen
or .event.listens_for
:
def validate_phone(target, value, oldvalue, initiator): "Strip non-numeric characters from a phone number" return re.sub(r'\D', '', value) # setup listener on UserContact.phone attribute, instructing # it to use the return value listen(UserContact.phone, 'set', validate_phone, retval=True)
A validation function like the above can also raise an exception
such as ValueError
to halt the operation.
The :paramref:`.AttributeEvents.propagate` flag is also important when applying listeners to mapped classes that also have mapped subclasses, as when using mapper inheritance patterns:
@event.listens_for(MySuperClass.attr, 'set', propagate=True) def receive_set(target, value, initiator): print("value set: %s" % target)
The full list of modifiers available to the .event.listen
and .event.listens_for
functions are below.
Parameters | |
active_history=False | When True, indicates that the
"set" event would like to receive the "old" value being
replaced unconditionally, even if this requires firing off
database loads. Note that active_history can also be
set directly via .column_property and
_orm.relationship . |
propagate=False | When True, the listener function will be established not just for the class attribute given, but for attributes of the same name on all current subclasses of that class, as well as all future subclasses of that class, using an additional listener that listens for instrumentation events. |
raw=False | When True, the "target" argument to the
event will be the .InstanceState management
object, rather than the mapped instance itself. |
retval=False | when True, the user-defined event listening must return the "value" argument from the function. This gives the listening function the opportunity to change the value that is ultimately used for a "set" or "append" event. |
Class Method | _accept_with |
Undocumented |
Class Method | _listen |
Undocumented |
Static Method | _set_dispatch |
Undocumented |
Method | append |
Receive a collection append event. |
Method | append_wo_mutation |
Receive a collection append event where the collection was not actually mutated. |
Method | bulk_replace |
Receive a collection 'bulk replace' event. |
Method | dispose_collection |
Receive a 'collection dispose' event. |
Method | init_collection |
Receive a 'collection init' event. |
Method | init_scalar |
Receive a scalar "init" event. |
Method | modified |
Receive a 'modified' event. |
Method | remove |
Receive a collection remove event. |
Method | set |
Receive a scalar set event. |
Class Variable | _target_class_doc |
Undocumented |
Inherited from Events
:
Class Method | _clear |
Undocumented |
Class Method | _remove |
Undocumented |
sqlalchemy.event.base.Events._listen
Undocumented
Receive a collection append event.
The append event is invoked for each element as it is appended to the collection. This occurs for single-item appends as well as for a "bulk replace" operation.
See Also
.AttributeEvents
- background on listener options such
as propagation to subclasses.
.AttributeEvents.bulk_replace
Parameters | |
target | the object instance receiving the event.
If the listener is registered with raw=True, this will
be the .InstanceState object. |
value | the value being appended. If this listener is registered with retval=True, the listener function must return this value, or a new value which replaces it. |
initiator | An instance of .attributes.Event
representing the initiation of the event. May be modified
from its original value by backref handlers in order to control
chained event propagation, as well as be inspected for information
about the source of the event. |
Returns | |
if the event was registered with retval=True, the given value, or a new effective value, should be returned. |
Receive a collection append event where the collection was not actually mutated.
This event differs from _orm.AttributeEvents.append
in that
it is fired off for de-duplicating collections such as sets and
dictionaries, when the object already exists in the target collection.
The event does not have a return value and the identity of the
given object cannot be changed.
The event is used for cascading objects into a _orm.Session
when the collection has already been mutated via a backref event.
Parameters | |
target | the object instance receiving the event.
If the listener is registered with raw=True, this will
be the .InstanceState object. |
value | the value that would be appended if the object did not already exist in the collection. |
initiator | An instance of .attributes.Event
representing the initiation of the event. May be modified
from its original value by backref handlers in order to control
chained event propagation, as well as be inspected for information
about the source of the event. |
Returns | |
No return value is defined for this event. |
Receive a collection 'bulk replace' event.
This event is invoked for a sequence of values as they are incoming to a bulk collection set operation, which can be modified in place before the values are treated as ORM objects. This is an "early hook" that runs before the bulk replace routine attempts to reconcile which objects are already present in the collection and which are being removed by the net replace operation.
It is typical that this method be combined with use of the
.AttributeEvents.append
event. When using both of these
events, note that a bulk replace operation will invoke
the .AttributeEvents.append
event for all new items,
even after .AttributeEvents.bulk_replace
has been invoked
for the collection as a whole. In order to determine if an
.AttributeEvents.append
event is part of a bulk replace,
use the symbol ~.attributes.OP_BULK_REPLACE
to test the
incoming initiator:
from sqlalchemy.orm.attributes import OP_BULK_REPLACE @event.listens_for(SomeObject.collection, "bulk_replace") def process_collection(target, values, initiator): values[:] = [_make_value(value) for value in values] @event.listens_for(SomeObject.collection, "append", retval=True) def process_collection(target, value, initiator): # make sure bulk_replace didn't already do it if initiator is None or initiator.op is not OP_BULK_REPLACE: return _make_value(value) else: return value
See Also
.AttributeEvents
- background on listener options such
as propagation to subclasses.
Parameters | |
target | the object instance receiving the event.
If the listener is registered with raw=True, this will
be the .InstanceState object. |
values | Undocumented |
initiator | An instance of .attributes.Event
representing the initiation of the event. |
value | a sequence (e.g. a list) of the values being set. The handler can modify this list in place. |
Receive a 'collection dispose' event.
This event is triggered for a collection-based attribute when a collection is replaced, that is:
u1.addresses.append(a1) u1.addresses = [a2, a3] # <- old collection is disposed
The old collection received will contain its previous contents.
.AttributeEvents.dispose_collection
will now have its
contents before the dispose intact; previously, the collection
would be empty..AttributeEvents.init_collection
and .AttributeEvents.dispose_collection
events.See Also
.AttributeEvents
- background on listener options such
as propagation to subclasses.
Receive a 'collection init' event.
This event is triggered for a collection-based attribute, when the initial "empty collection" is first generated for a blank attribute, as well as for when the collection is replaced with a new one, such as via a set event.
E.g., given that User.addresses is a relationship-based collection, the event is triggered here:
u1 = User() u1.addresses.append(a1) # <- new collection
and also during replace operations:
u1.addresses = [a2, a3] # <- new collection
.AttributeEvents.init_collection
and .AttributeEvents.dispose_collection
events.See Also
.AttributeEvents
- background on listener options such
as propagation to subclasses.
.AttributeEvents.init_scalar
- "scalar" version of this
event.
Parameters | |
target | the object instance receiving the event.
If the listener is registered with raw=True, this will
be the .InstanceState object. |
collection | the new collection. This will always be generated from what was specified as :paramref:`_orm.relationship.collection_class`, and will always be empty. |
collection_adapter | the .CollectionAdapter that will
mediate internal access to the collection. |
Receive a scalar "init" event.
This event is invoked when an uninitialized, unpersisted scalar attribute is accessed, e.g. read:
x = my_object.some_attribute
The ORM's default behavior when this occurs for an un-initialized
attribute is to return the value None; note this differs from
Python's usual behavior of raising AttributeError. The
event here can be used to customize what value is actually returned,
with the assumption that the event listener would be mirroring
a default generator that is configured on the Core
_schema.Column
object as well.
Since a default generator on a _schema.Column
might also produce
a changing value such as a timestamp, the
.AttributeEvents.init_scalar
event handler can also be used to set the newly returned value, so
that a Core-level default generation function effectively fires off
only once, but at the moment the attribute is accessed on the
non-persisted object. Normally, no change to the object's state
is made when an uninitialized attribute is accessed (much older
SQLAlchemy versions did in fact change the object's state).
If a default generator on a column returned a particular constant, a handler might be used as follows:
SOME_CONSTANT = 3.1415926 class MyClass(Base): # ... some_attribute = Column(Numeric, default=SOME_CONSTANT) @event.listens_for( MyClass.some_attribute, "init_scalar", retval=True, propagate=True) def _init_some_attribute(target, dict_, value): dict_['some_attribute'] = SOME_CONSTANT return SOME_CONSTANT
Above, we initialize the attribute MyClass.some_attribute to the value of SOME_CONSTANT. The above code includes the following features:
_schema.Column
. The active_column_defaults.py
example given at :ref:`examples_instrumentation` illustrates using
the same approach for a changing default, e.g. a timestamp
generator. In this particular example, it is not strictly
necessary to do this since SOME_CONSTANT would be part of the
INSERT statement in either case.In the above example, the attribute set event
.AttributeEvents.set
as well as the related validation feature
provided by _orm.validates
is not invoked when we apply our
value to the given dict_. To have these events to invoke in
response to our newly generated value, apply the value to the given
object as a normal attribute set operation:
SOME_CONSTANT = 3.1415926 @event.listens_for( MyClass.some_attribute, "init_scalar", retval=True, propagate=True) def _init_some_attribute(target, dict_, value): # will also fire off attribute set events target.some_attribute = SOME_CONSTANT return SOME_CONSTANT
When multiple listeners are set up, the generation of the value is "chained" from one listener to the next by passing the value returned by the previous listener that specifies retval=True as the value argument of the next listener.
See Also
.AttributeEvents.init_collection
- collection version
of this event
.AttributeEvents
- background on listener options such
as propagation to subclasses.
:ref:`examples_instrumentation` - see the active_column_defaults.py example.
Parameters | |
target | the object instance receiving the event.
If the listener is registered with raw=True, this will
be the .InstanceState object. |
value | the value that is to be returned before this event listener were invoked. This value begins as the value None, however will be the return value of the previous event handler function if multiple listeners are present. |
dict_ | the attribute dictionary of this mapped object. This is normally the __dict__ of the object, but in all cases represents the destination that the attribute system uses to get at the actual value of this attribute. Placing the value in this dictionary has the effect that the value will be used in the INSERT statement generated by the unit of work. |
Receive a 'modified' event.
This event is triggered when the .attributes.flag_modified
function is used to trigger a modify event on an attribute without
any specific value being set.
See Also
.AttributeEvents
- background on listener options such
as propagation to subclasses.
Parameters | |
target | the object instance receiving the event.
If the listener is registered with raw=True, this will
be the .InstanceState object. |
initiator | An instance of .attributes.Event
representing the initiation of the event. |
Receive a collection remove event.
See Also
.AttributeEvents
- background on listener options such
as propagation to subclasses.
Parameters | |
target | the object instance receiving the event.
If the listener is registered with raw=True, this will
be the .InstanceState object. |
value | the value being removed. |
initiator | An instance of
Changed in version 0.9.0: the initiator argument is now
passed as a
.attributes.Event object, and may be
modified by backref handlers within a chain of backref-linked
events. |
Returns | |
No return value is defined for this event. |
Receive a scalar set event.
See Also
.AttributeEvents
- background on listener options such
as propagation to subclasses.
Parameters | |
target | the object instance receiving the event.
If the listener is registered with raw=True, this will
be the .InstanceState object. |
value | the value being set. If this listener is registered with retval=True, the listener function must return this value, or a new value which replaces it. |
oldvalue | the previous value being replaced. This may also be the symbol NEVER_SET or NO_VALUE. If the listener is registered with active_history=True, the previous value of the attribute will be loaded from the database if the existing value is currently unloaded or expired. |
initiator | An instance of
Changed in version 0.9.0: the initiator argument is now
passed as a
.attributes.Event object, and may be
modified by backref handlers within a chain of backref-linked
events. |
Returns | |
if the event was registered with retval=True, the given value, or a new effective value, should be returned. |