Как я могу определить, когда экземпляры удаляются с помощью каскада «удаление-сирота»?

#python #sqlalchemy #all-delete-orphan

#python #sqlalchemy #все-удалить-сироту

Вопрос:

Я пытаюсь добавить ведение журнала аудита для некоторых моих таблиц, которые я реализовал в 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 слушателя) удалено?