Hello, 

thanks again for the answer. Perhaps my case was not clear enough. To make 
it a bit more explicit, I updated the example accordingly. 

from sqlalchemy import event

from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, backref, relationship

Base = declarative_base()


#########################################################################################
# MODEL
#########################################################################################
class House(Base):
    __tablename__ = 'house'
    id = Column(Integer, primary_key=True)
    rooms = relationship("Room",
                         backref=backref("house", lazy="joined"),
                         cascade='all, delete-orphan')


class Room(Base):
    __tablename__ = 'room'
    id = Column(Integer, primary_key=True)
    house_id = Column(Integer, ForeignKey('house.id'))
    beds = relationship("Bed",
                        backref=backref("room", lazy="joined"),
                        cascade='all, delete-orphan')


class Bed(Base):
    __tablename__ = 'bed'
    id = Column(Integer, primary_key=True)
    room_id = Column(Integer, ForeignKey('room.id'))


#########################################################################################
# CONFIG
#########################################################################################
def setup():
    engine = create_engine("sqlite://", echo=True)

    Base.metadata.bind = engine
    Base.metadata.create_all(engine)

    SessionFactory = sessionmaker(
        bind=engine
    )

    event.listen(SessionFactory, 'deleted_to_detached', 
listener_bed_has_been_removed)

    return SessionFactory


def listener_bed_has_been_removed(session, instance):
    if type(instance) is not Bed:
        return

    # so, in this example, this function should be called 3 times.
    # The first time it is called, I get no problems, I can access 
instance.room.house_id the call proceeds
    # The second bed is a problem, I get the error
    # "sqlalchemy.orm.exc.DetachedInstanceError: Parent instance <Bed at 
0x7f24fe14bb70> is not bound to a Session; lazy load operation of attribute 
'room' cannot proceed"

    # SO, my question is: is there ANY way to keep these references to parents 
in this function?

    bed_id = instance.id
    house_id = instance.room.house_id


    print("execute a service call to external service here bed_id {}, house_id 
{}".format(bed_id, house_id))


if __name__ == "__main__":
    session_factory = setup()
    session = session_factory()

    session.add(House(id=1))
    session.add(Room(id=1, house_id=1))
    session.add(Bed(id=1, room_id=1))
    session.add(Bed(id=2, room_id=1))
    session.add(Bed(id=3, room_id=1))
    session.commit()

    room = session.query(Room).get(1)
    session.delete(room)
    session.commit()
    session.close()


So, for this example, I am looking for a solution to keep the references to 
the 'house' from the 'bed' model after flush (any solution would be good). 
Is there perhaps a way to dynamically set a property in 'bed' -model (e.g 
house_id), once 'room'-backref has been loaded ?


On Tuesday, August 22, 2017 at 5:36:39 PM UTC+2, Mike Bayer wrote:
>
> you would need to illustrate an MCVE of what's happening.  objects 
> don't "lose track" of their related objects unless yes, you deleted 
> them, in which case you should not expect that they would be there. 
> when the object is expired, it will go to reload them, and they'll be 
> gone. 
>
> On Tue, Aug 22, 2017 at 11:05 AM, cecemel <ruiz.fe...@gmail.com 
> <javascript:>> wrote: 
> > @update: 
> > 
> > calling the flush doen't seem to make any difference. At some point, the 
> > object looses track of it's grandparents 
> > 
> > 
> > On Tuesday, August 22, 2017 at 3:57:23 PM UTC+2, cecemel wrote: 
> >> 
> >> Hi, 
> >> 
> >> so, I'm currently facing this issue, where I would like to do some 
> calls 
> >> to an external service, when my object has been deleted within a flush. 
> >> For this operation to occur, I need the id from my model object, but 
> also 
> >> the id from the parent of the parent object model. There are cases, 
> where I 
> >> am unable to access them (I guess, depending of the order of the 
> execution) 
> >> and I am unsure on what to do next. 
> >> 
> >> So if you're willing to give me some advice, would be awesome. 
> >> 
> >> Here is a dummy model: 
> >> 
> >> from sqlalchemy import event 
> >> 
> >> from sqlalchemy import * 
> >> from sqlalchemy.ext.declarative import declarative_base 
> >> from sqlalchemy.orm import sessionmaker, backref, relationship 
> >> 
> >> Base = declarative_base() 
> >> 
> >> 
> >> 
> >> 
> #########################################################################################
>  
>
> >> # MODEL 
> >> 
> >> 
> #########################################################################################
>  
>
> >> class House(Base): 
> >>     __tablename__ = 'house' 
> >>     id = Column(Integer, primary_key=True) 
> >>     rooms = relationship("Room", 
> >>                          backref=backref("house", lazy="joined"), 
> >>                          cascade='all, delete-orphan') 
> >> 
> >> 
> >> class Room(Base): 
> >>     __tablename__ = 'room' 
> >>     id = Column(Integer, primary_key=True) 
> >>     house_id = Column(Integer, ForeignKey('house.id')) 
> >>     beds = relationship("Bed", 
> >>                         backref=backref("room", lazy="joined"), 
> >>                         cascade='all, delete-orphan') 
> >> 
> >> 
> >> class Bed(Base): 
> >>     __tablename__ = 'bed' 
> >>     id = Column(Integer, primary_key=True) 
> >>     room_id = Column(Integer, ForeignKey('room.id')) 
> >> 
> >> 
> >> 
> >> 
> #########################################################################################
>  
>
> >> # CONFIG 
> >> 
> >> 
> #########################################################################################
>  
>
> >> def setup(): 
> >>     engine = create_engine("sqlite:///foo.db", echo=True) 
> >> 
> >>     Base.metadata.bind = engine 
> >>     Base.metadata.create_all(engine) 
> >> 
> >>     SessionFactory = sessionmaker( 
> >>         bind=engine 
> >>     ) 
> >> 
> >>     event.listen(SessionFactory, 'deleted_to_detached', 
> >> listener_bed_has_been_removed) 
> >> 
> >>     return SessionFactory 
> >> 
> >> 
> >> def listener_bed_has_been_removed(session, instance): 
> >>     if type(instance) is not Bed: 
> >>         return 
> >> 
> >>     bed_id = instance.id 
> >>     house_id = instance.room.house.id  # this is NOT ALWAYS there. 
> >> Depending on the order of the execution I guess 
> >> 
> >>     print("execute the service call to external service here bed_id {}, 
> >> house_id {}".format(bed_id, house_id)) 
> >> 
> >> 
> >> 
> >> 
> >> So my question(s): 
> >> 
> >> Is there a clean way to always acces this parent's parent attribute? 
> >> 
> >> If not, would be starting a new session and query it from the event 
> >> handler be an option? (is it not dangerous, because it seems to work) 
> >> 
> >> Additional quirk, I am working within a transaction manager 
> (pyramid_tm) 
> >> and ZopeTransactionExtension() 
> >> 
> >> Thanks! 
> >> 
> >> 
> >> More information about the system: 
> >> 
> >> SQLAlchemy 1.1.13 
> >> 
> >> Python 3.5 
> >> 
> >> Postgres 9.6 
> > 
> > -- 
> > SQLAlchemy - 
> > The Python SQL Toolkit and Object Relational Mapper 
> > 
> > http://www.sqlalchemy.org/ 
> > 
> > To post example code, please provide an MCVE: Minimal, Complete, and 
> > Verifiable Example. See http://stackoverflow.com/help/mcve for a full 
> > description. 
> > --- 
> > You received this message because you are subscribed to the Google 
> Groups 
> > "sqlalchemy" group. 
> > To unsubscribe from this group and stop receiving emails from it, send 
> an 
> > email to sqlalchemy+...@googlegroups.com <javascript:>. 
> > To post to this group, send email to sqlal...@googlegroups.com 
> <javascript:>. 
> > Visit this group at https://groups.google.com/group/sqlalchemy. 
> > For more options, visit https://groups.google.com/d/optout. 
>

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to