I am using a MapperExtension to implement trigger-like functions in my app and needed an after_delete event. Attached is a patch which implements the needed changes to Mapper.py (also updates adv_datamapping.myt docs).
Sean Cazzell
Index: doc/build/content/adv_datamapping.txt =================================================================== --- doc/build/content/adv_datamapping.txt (revision 1492) +++ doc/build/content/adv_datamapping.txt (working copy) @@ -787,6 +787,8 @@ """called after an object instance has been INSERTed""" def before_delete(self, mapper, connection, instance): """called before an object instance is DELETEed""" + def after_delete(self, mapper, connection, instance): + """called after an object instance is DELETEed""" To use MapperExtension, make your own subclass of it and just send it off to a mapper: Index: lib/sqlalchemy/orm/mapper.py =================================================================== --- lib/sqlalchemy/orm/mapper.py (revision 1492) +++ lib/sqlalchemy/orm/mapper.py (working copy) @@ -682,6 +682,7 @@ if not self._has_pks(table): continue delete = [] + deleted_objects = [] for obj in objects: params = {} if not hasattr(obj, "_instance_key"): @@ -693,6 +694,7 @@ if self.version_id_col is not None: params[self.version_id_col.key] = self._getattrbycolumn(obj, self.version_id_col) self.extension.before_delete(self, connection, obj) + deleted_objects.append(obj) if len(delete): clause = sql.and_() for col in self.pks_by_table[table]: @@ -703,6 +705,8 @@ c = connection.execute(statement, delete) if c.supports_sane_rowcount() and c.rowcount != len(delete): raise exceptions.FlushError("ConcurrencyError - updated rowcount %d does not match number of objects updated %d" % (c.cursor.rowcount, len(delete))) + for obj in deleted_objects: + self.extension.after_delete(self, connection, obj) def _has_pks(self, table): try: @@ -1078,6 +1082,10 @@ """called before an object instance is DELETEed""" if self.next is not None: self.next.before_delete(mapper, connection, instance) + def after_delete(self, mapper, connection, instance): + """called after an object instance is DELETEed""" + if self.next is not None: + self.next.after_delete(mapper, connection, instance) class TranslatingDict(dict): """a dictionary that stores ColumnElement objects as keys. incoming ColumnElement