I have a new question about SQLAlchemy and I broke my brain while try to find a good solution. So I've a some tables:
import sqlalchemy.orm.session
# other import statments . . .
Session = sqlalchemy.orm.session.Session
class Tempable(Base):
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False, unique=True)
temporary = Column(Boolean, nullable=False)
class Generic(Base):
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False, unique=True)
tempable_id = Column(Integer, ForeignKey(Tempable.id))
Tempable table has a field named temporary. When this field is True then only one Generic can be relate to this Tempable table row and when related Generic row deleted then Tempable must also be deleted. Otherwise many Generic can be connected with Tempable and removing one of them don't affect to Tempable.
After some researches I've figured out that must convient way to do this is using of events. Code expanded to the follows:
class Generic(Base):
# . . .
def before_delete(self, session):
""":type session: Session"""
condition = and_(Tempable.id == self.tempable_id, Tempable.temporary == 1)
# I've tried use bulk session deletion:
# session.query(Tempable).filter(condition).delete()
# but if Tempable tables has relationships then related objects not deleted,
# I don't understand such behaviour.
# But this works fine:
for obj in session.query(Tempable).filter(condition):
session.delete(obj)
@event.listens_for(Session, 'before_flush')
def _database_flush(session, flush_context, instances):
for p_object in session.deleted:
if hasattr(p_object, "before_delete"):
p_object.before_delete(session)
for p_object in session.dirty:
if hasattr(p_object, "before_update"):
p_object.before_update(session)
for p_object in session.new:
if hasattr(p_object, "before_insert"):
p_object.before_insert(session)
But some troubles occurred. When Generic object deleted the corresponding GUI must be also updated. For this purpose deleted property of Session object can be used. But also there is a problem for me: deleted Tempable row not appeared in this property list.
class Database(object):
# . . .
def remove(name):
# before commit I need to obtain list of all objects that will be deleted
# that required to update GUI views
try:
this = self.__session.query(orm.Generic).filter(orm.Generic.name == name).one()
except orm.NoResultFound:
pass
else:
logging.info("Remove object: %s" % this)
self.__session.delete(this)
deleted = [obj for obj in self.__session.deleted]
# At this point, list of deleted objects of course is not contain any Tempable objects
print(deleted)
self.__session.commit()
# And here list is empty
print([obj for obj in self.__session.deleted])
return deleted
So the question what is right way to do obtain deleted objects or may be the whole approach is totally wrong?