from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

atob = Table(
    'atob', Base.metadata,
    Column('aid', ForeignKey('a.id'), primary_key=True),
    Column('bid', ForeignKey('b.id'), primary_key=True)
)


class A(Base):
    __tablename__ = 'a'
    id = Column(Integer, primary_key=True)
    bs = relationship("B", secondary=atob)


class B(Base):
    __tablename__ = 'b'
    id = Column(Integer, primary_key=True)

e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)


session = Session(e)

a1 = A(bs=[B(), B(), B()])
session.add(a1)
session.commit()


# please illustrate failure here

#
# Example 1. M2M is empty after being made transient.
#

assert len(a1.bs) == 3

make_transient(a1)
a1.id = None
session.add(a1)
session.commit()

assert len(a1.bs) == 0

#
# Example 2. M2M remains empty ever after being assigned relationships.
#

model = session.query(A).first()
bs = model.bs.copy()
assert len(bs) == 3

make_transient(model)
model.id = None
model.bs = bs
session.add(model)
session.commit()

assert len(model.bs) == 0

#
# Example 3. M2M is populated from fresh query.
#

model = session.query(A).first()
bs = session.query(B).all()
assert len(bs) == 3

make_transient(model)
model.id = None
model.bs = bs
session.add(model)
session.commit()
assert len(model.bs) == 3


On Friday, October 28, 2016 at 9:47:44 AM UTC-4, Mike Bayer wrote:
>
> here we are, please complete and return, thanks 
>
> from sqlalchemy import * 
> from sqlalchemy.orm import * 
> from sqlalchemy.ext.declarative import declarative_base 
>
> Base = declarative_base() 
>
> atob = Table( 
>      'atob', Base.metadata, 
>      Column('aid', ForeignKey('a.id'), primary_key=True), 
>      Column('bid', ForeignKey('b.id'), primary_key=True) 
> ) 
>
>
> class A(Base): 
>      __tablename__ = 'a' 
>      id = Column(Integer, primary_key=True) 
>      bs = relationship("B", secondary=atob) 
>
>
> class B(Base): 
>      __tablename__ = 'b' 
>      id = Column(Integer, primary_key=True) 
>
> e = create_engine("sqlite://", echo=True) 
> Base.metadata.create_all(e) 
>
>
> session = Session(e) 
>
> a1 = A(bs=[B(), B(), B()]) 
> session.add(a1) 
> session.commit() 
>
>
> # please illustrate failure here 
>
>
>
>
>
> On 10/28/2016 09:13 AM, Colton Allen wrote: 
> > Okay I see.  That does remove the error.  But I am having trouble saving 
> > the relationship.  Check the example code.  It is much clearer than I 
> am. 
> > 
> > If I query a new set of items or specify an item model instance it will 
> > save perfectly.  But all of the instances in the instrumented list will 
> > not save to the relationship.  Is there a further expiration step? 
> > 
> > # This works 
> > session.expire(model, ['items']) 
> > make_transient(model) 
> > model.items = ItemModel.query.all() # [<ItemModel>] 
> > session.add(model) 
> > session.commit() 
> > 
> > Test.query.first().items # [<ItemModel>] 
> > 
> > # This does not save 
> > items = model.items.copy()  # [<ItemModel>] 
> > session.expire(model, ['items']) 
> > make_transient(model) 
> > model.items = items 
> > session.add(model) 
> > session.commit() 
> > 
> > Test.query.first().items # [] 
> > 
> > On Thursday, October 27, 2016 at 6:15:39 PM UTC-4, Mike Bayer wrote: 
> > 
> >     you'd say: 
> > 
> >     session.expire(model, ["items"]) 
> > 
> > 
> > 
> >     On 10/27/2016 04:47 PM, Colton Allen wrote: 
> >     > Sorry I must have combined multiple attempts into one example. 
> >      When you 
> >     > say expire the relationship, what do you mean? 
> >     > 
> >     > 
> >     > On Thursday, October 27, 2016 at 4:30:36 PM UTC-4, Mike Bayer 
> wrote: 
> >     > 
> >     >     Hello - 
> >     > 
> >     > 
> >     >     I've rebuilt your fragment into a full example in order to 
> >     determine 
> >     >     what the behavior is here, as make_transient() has no defined 
> >     behavior 
> >     >     for loaded relationships. 
> >     > 
> >     >     Your error does not reproduce with your code fragment as 
> >     given, because 
> >     >     you are setting the list of items to itself, and this means 
> >     there is no 
> >     >     history at all; the unit of work will ignore it. 
> >     > 
> >     >     Setting the list to a series of three brand new secondary 
> items 
> >     >     produces 
> >     >     the error you see because this generates deletion events for 
> the 
> >     >     existing objects which fail because the state of the object is 
> >     >     transient. 
> >     > 
> >     >     The solution is to expire the relationship attribute first so 
> >     that 
> >     >     it is 
> >     >     reset for the transient state. 
> >     > 
> >     > 
> >     > 
> >     > 
> >     >     On 10/27/2016 03:43 PM, Colton Allen wrote: 
> >     >     > I want to create a new row with all of the same data. 
>  However, 
> >     >     (using 
> >     >     > make_transient) the many-to-many "items" relationship 
> doesn't 
> >     >     carry over 
> >     >     > to the new model.  When I manually set the items I recieve a 
> >     >     > "StaleDataError".  How can I insert the many-to-many 
> >     relationships so 
> >     >     > this does not happen? 
> >     >     > * 
> >     >     > * 
> >     >     > * 
> >     >     > My code:* 
> >     >     > 
> >     >     > class Test(Model): 
> >     >     >     id = Column(Integer, primary_key=True) 
> >     >     >     items = orm.relationship('ItemModel', 
> >     secondary=test_item_table) 
> >     >     > 
> >     >     > 
> >     >     > model = Test.query.first() 
> >     >     > list_of_items = model.items.copy() 
> >     >     > 
> >     >     > make_transient(model) 
> >     >     > model.id <http://model.id> <http://model.id> = None 
> >     >     > model.items = list_of_items 
> >     >     > 
> >     >     > session.add(model) 
> >     >     > session.commit() 
> >     >     > 
> >     >     > # sqlalchemy.orm.exc.StaleDataError: DELETE statement on 
> table 
> >     >     > 'test_item' expected to delete 1 row(s); Only 0 were 
> matched. 
> >     >     > 
> >     >     > -- 
> >     >     > 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 
> >     <http://stackoverflow.com/help/mcve> 
> >     >     <http://stackoverflow.com/help/mcve 
> >     <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:> 
> >     >     > <mailto:sqlalchemy+unsubscr...@googlegroups.com 
> <javascript:> 
> >     <javascript:> <javascript:>>. 
> >     >     > To post to this group, send email to 
> sqlal...@googlegroups.com 
> >     >     <javascript:> 
> >     >     > <mailto:sqlal...@googlegroups.com <javascript:>>. 
> >     >     > Visit this group at 
> >     https://groups.google.com/group/sqlalchemy 
> >     <https://groups.google.com/group/sqlalchemy> 
> >     >     <https://groups.google.com/group/sqlalchemy 
> >     <https://groups.google.com/group/sqlalchemy>>. 
> >     >     > For more options, visit https://groups.google.com/d/optout 
> >     <https://groups.google.com/d/optout> 
> >     >     <https://groups.google.com/d/optout 
> >     <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 
> >     <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:> 
> >     > <mailto:sqlalchemy+unsubscr...@googlegroups.com <javascript:> 
> <javascript:>>. 
> >     > To post to this group, send email to sqlal...@googlegroups.com 
> >     <javascript:> 
> >     > <mailto:sqlal...@googlegroups.com <javascript:>>. 
> >     > Visit this group at https://groups.google.com/group/sqlalchemy 
> >     <https://groups.google.com/group/sqlalchemy>. 
> >     > For more options, visit https://groups.google.com/d/optout 
> >     <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+...@googlegroups.com <javascript:> 
> > <mailto:sqlalchemy+unsubscr...@googlegroups.com <javascript:>>. 
> > To post to this group, send email to sqlal...@googlegroups.com 
> <javascript:> 
> > <mailto: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