This is a full example that shows how mixin classes can be implemented for use with SQLALchemy in a way that also automatically apply event listeners to appropriate subclasses of a given mixin class. The use case started with this question on StackOverflow which asked about how the before_delete
mapper event can be used, which lead down the path of exploration that lead to this more generic skeleton on how this might be achieved in a more generic manner.
The following is an example run of the associated Python code:
INFO:sqlalchemy.engine.Engine:SELECT entity.id AS entity_id, entity.field_a AS entity_field_a, entity.field_b AS entity_field_b, entity.created_at AS entity_created_at, entity.deleted_at AS entity_deleted_at
FROM entity
INFO:sqlalchemy.engine.Engine:[generated in 0.00009s] ()
INFO:__main__:<Entity id=1> is deleted
INFO:sqlalchemy.engine.Engine:UPDATE entity SET deleted_at=? WHERE entity.id = ?
INFO:sqlalchemy.engine.Engine:[generated in 0.00011s] ('2023-04-01 00:20:14.149779', 1)
INFO:sqlalchemy.engine.Engine:COMMIT
INFO:sqlalchemy.engine.Engine:BEGIN (implicit)
INFO:sqlalchemy.engine.Engine:SELECT entity.id AS entity_id, entity.field_a AS entity_field_a, entity.field_b AS entity_field_b, entity.created_at AS entity_created_at, entity.deleted_at AS entity_deleted_at
FROM entity
INFO:sqlalchemy.engine.Engine:[cached since 0.002176s ago] ()
INFO:__main__:<Entity id=1> is undeleted
INFO:sqlalchemy.engine.Engine:UPDATE entity SET deleted_at=? WHERE entity.id = ?
INFO:sqlalchemy.engine.Engine:[cached since 0.001268s ago] (None, 1)
INFO:sqlalchemy.engine.Engine:UPDATE entity SET field_a=? WHERE entity.id = ?
INFO:sqlalchemy.engine.Engine:[generated in 0.00009s] ('id:3 updated field_a', 3)
INFO:sqlalchemy.engine.Engine:COMMIT
INFO:sqlalchemy.engine.Engine:BEGIN (implicit)
INFO:sqlalchemy.engine.Engine:SELECT document.id AS document_id, document.title AS document_title, document.deleted_at AS document_deleted_at
FROM document
LIMIT ? OFFSET ?
INFO:sqlalchemy.engine.Engine:[generated in 0.00010s] (1, 0)
INFO:__main__:<Document id=1> is deleted
INFO:sqlalchemy.engine.Engine:UPDATE document SET deleted_at=? WHERE document.id = ?
INFO:sqlalchemy.engine.Engine:[generated in 0.00011s] ('2023-04-01 00:20:14.154136', 1)
INFO:sqlalchemy.engine.Engine:SELECT user.id AS user_id, user.name AS user_name, user.deleted_at AS user_deleted_at
FROM user
LIMIT ? OFFSET ?
INFO:sqlalchemy.engine.Engine:[generated in 0.00013s] (1, 0)
INFO:__main__:<User id=1> is deleted
INFO:sqlalchemy.engine.Engine:UPDATE user SET deleted_at=? WHERE user.id = ?
INFO:sqlalchemy.engine.Engine:[generated in 0.00010s] ('2023-04-01 00:20:14.155961', 1)
INFO:sqlalchemy.engine.Engine:COMMIT
INFO:sqlalchemy.engine.Engine:BEGIN (implicit)
INFO:sqlalchemy.engine.Engine:SELECT document.id AS document_id, document.title AS document_title, document.deleted_at AS document_deleted_at
FROM document
LIMIT ? OFFSET ?
INFO:sqlalchemy.engine.Engine:[cached since 0.003432s ago] (1, 0)
INFO:sqlalchemy.engine.Engine:COMMIT