How to intercept delete() with do_orm_execute()?
#10358
-
|
The docs are explicit that ORM I've tried implementing a rewrite of # Soft delete hook
@listens_for(Session, identifier="do_orm_execute")
def soft_delete_execute(state: ORMExecuteState):
"""Hook to filter soft-deleted objects out of selects and rewrite deletes as soft deletes."""
if state.is_select and not state.statement.get_execution_options().get(
"include_deleted"
):
state.statement = state.statement.options(
with_loader_criteria(
SoftDeleteMixin,
lambda cls: cls.deleted_at.is_(None),
include_aliases=True,
)
)
if isinstance(state.statement, Delete):
# This code is never reached!
state.statement = rewrite_delete(state.statement)# Test case
def test_orm_delete(self, session: Session):
"""Test that the event hook intercepts a delete statement."""
user = session.get(User, 1)
session.delete(user)
session.commit()
# assert the user is soft-deleted
assert user.deleted_at is not None |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
|
session.delete() is a unit of work method and is intercepted by before_delete and after_delete. The do_orm_execute hook only applies to objects passed to session.execute(): https://docs.sqlalchemy.org/en/20/orm/session_events.html#basic-query-interception
that is, the delete construct noted at: https://docs.sqlalchemy.org/en/20/core/dml.html#sqlalchemy.sql.expression.delete the tutorial at https://docs.sqlalchemy.org/en/20/tutorial/orm_data_manipulation.html#bulk-multi-row-insert-upsert-update-and-delete attempts to contrast the use of the |
Beta Was this translation helpful? Give feedback.
-
|
Thank you @zzzeek, that was very helpful. For anyone interested I wrote a second hook as follows: @listens_for(Session, "before_flush")
def soft_delete_unit_of_work(session: Session, flush_context, instances):
"""Hook to alter unit of work deletes to soft deletes."""
for instance in session.deleted:
if isinstance(instance, SoftDeleteMixin):
instance.deleted_at = func.now()
session.add(instance) |
Beta Was this translation helpful? Give feedback.
session.delete() is a unit of work method and is intercepted by before_delete and after_delete. The do_orm_execute hook only applies to objects passed to session.execute():
https://docs.sqlalchemy.org/en/20/orm/session_events.html#basic-query-interception
that is, the delete construct noted at: https://docs.sqlalchemy.org/en/20/core/dml.html#sqlalchemy.sql.expression.delete
the tutorial at https://docs.sqlalchemy.org/en/20/tutorial/…