Как я могу определить, когда экземпляры удаляются с помощью каскада "удалить сироту"?
Я пытаюсь добавить журнал аудита для некоторых из моих таблиц, который я реализовал в after_flush
слушатель. Получая доступ к состоянию сеанса в session.new
/dirty
/deleted
Я могу получить информацию, которая мне нужна.
Ну, по крайней мере, в большинстве случаев: мне не везет, когда я идентифицирую экземпляры, которые удаляются через каскад "удаления-сироты". Эти случаи не отображаются в session.deleted
, но вместо этого в session.dirty
и я не могу найти способ определить, будут ли они удалены.
Используя эту игрушечную модель для иллюстрации:
class Author(Base):
__tablename__ = 'authors'
id = Column(Integer, primary_key=True)
name = Column(String)
posts = relationship('Post', back_populates='author', cascade='all, delete-orphan')
def __repr__(self):
return 'Author(name={0.name})'.format(self)
class Post(Base):
__tablename__ = 'posts'
id = Column(Integer, primary_key=True)
content = Column(String)
author_id = Column(Integer, ForeignKey('authors.id'))
author = relationship('Author', back_populates='posts')
def __repr__(self):
return 'Post(content={0.content})'.format(self)
Идентификация регулярных добавлений / обновлений / удалений работает по назначению:
In [1]: session = Session()
...: jane = Author(name='Jane')
...: jane.posts = [Post(content='The nature of things'), Post(content='On the origin of stuff')]
...: session.add(jane)
...: session.new
Out[1]: IdentitySet([Author(name=Jane), Post(content=On the origin of stuff), Post(content=The nature of things)])
In [2]: session.flush()
...: jane.name = 'John'
...: session.dirty
Out[2]: IdentitySet([Author(name=John)])
In [3]: session.flush()
...: post = jane.posts[0]
...: session.delete(post)
...: session.deleted
Out[3]: IdentitySet([Post(content=The nature of things)])
Пока все хорошо. Тем не менее, когда я обновляю сообщения автора через отношение, которое приводит к удалению сообщения "происхождение материала" через каскад, это исключенное сообщение отображается только как грязное, а не как удаленное:
In [4]: session.flush()
...: jane.posts = [Post(content='Matter matters!')]
...: session.deleted
Out[4]: IdentitySet([])
In [5]: session.dirty
Out[5]: IdentitySet([Author(name=Jane), Post(content=On the origin of stuff)])
Как я могу обнаружить, что это сообщение будет (или было, в случае after_flush
слушатель) удалили?