On 01/01/2016 01:56 PM, Yegor Roganov wrote:
> Is there an option to make sqlalchemy populate foreign key column(s)
> when a relationship is set?
> Basically I want the following:
> 
> child.parent = parent
> assert child.parent_id == parent.id

just call session.flush() and this assertion will succeed.

There is an event which is called when the "set" occurs, however calling
session.flush() here wouldn't work because the event is fired before the
actual set operation takes place.

Automating this flush would require use of a @property so that the "set"
event of "child.parent" can be intercepted and some code can be invoked
after the actual set takes place.   The attribute would then be mapped
to an alternate name like "_parent".

Alternatively, if the action here doesn't need to be generalized, just
set the foreign key yourself with the "set" event and the flush wouldn't
be needed:

@event.listens_for(child.parent, "set")
def _set_parent(target, value, oldvalue, initiator):
    target.parent_id = value.id




> 
> Here is a full example you can run:
> |
> fromsqlalchemy.ext.declarative importdeclarative_base
> fromsqlalchemy importColumn,ForeignKey,Integer,String
> fromsqlalchemy importcreate_engine
> fromsqlalchemy.orm importsessionmaker,relationship
> 
> 
> Base=declarative_base()
> 
> 
> classParent(Base):
>     __tablename__ ='parent'
>     id =Column(Integer,primary_key=True)
> 
> 
> classChild(Base):
>     __tablename__ ='child'
>     id =Column(Integer,primary_key=True)
>     parent_id =Column(ForeignKey(Parent.id),nullable=False)
> 
>     parent =relationship(Parent,backref='children')
> 
> 
> engine =create_engine('sqlite:///:memory:',echo=True)
> Session=sessionmaker(bind=engine)
> 
> 
> defrun():
>     Base.metadata.create_all(engine)
>     session =Session()
>     parent1 =Parent(id=1)
>     session.add(parent1)
>     session.commit()
> 
> 
>     child =Child(parent=parent1)
>     printchild.parent_id,": None, but I'd like it to be 1"
>     session.add(child)
>     session.commit()
> 
> 
>     parent2 =Parent(id=2)
>     session.add(parent2)
>     session.commit()
>     child.parent =parent2
>     t =child.parent_id,child.parent.id
>     printt,": child.parent_id is stale!"
> 
> 
> 
> 
> if__name__ =='__main__':
>     run()
> |
> 
> 
> -- 
> 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
> <mailto:sqlalchemy+unsubscr...@googlegroups.com>.
> To post to this group, send email to sqlalchemy@googlegroups.com
> <mailto:sqlalchemy@googlegroups.com>.
> Visit this group at https://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/d/optout.

-- 
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