I just tried it again, and it works. Sorry for the confusion. Knowing
myself, I misspelled something when I tried it the first time.

-Lyla

On Sun, Apr 28, 2019 at 9:57 PM Mike Bayer <mike...@zzzcomputing.com> wrote:

> On Sun, Apr 28, 2019 at 9:17 PM <lylafi...@gmail.com> wrote:
> >
> > Thanks for the quick responses, and for adding the warning for others!
> >
> > I tried adding the lines as suggested (
> >
> > head = relationship("Head", backref="tassel_threads",
> cascade_backrefs=False)
> >
> > , but I keep getting the same error.
>
> with the specific test case you gave, adding cascade_backrefs to
> *both* relationships as above resolves the assertion at the end.  Is
> this assertion "the error" you're referring towards ?  I've tested in
> 1.3 as well as 1.2.  Is there a new test case you can provide ?
>
>
> > I also tried cascade=None, as James suggested, but that seemed to mess
> up the ability of the relationships to get at each other's primary keys or
> establish relationships with each other. I ended up solving the issue by
> removing some of the merges. That means that I'm depending on the cascading
> to get everything into the database and linked up appropriately, andt I
> might need to spend some time studying exactly how cascading works in order
> to be able to reliably use the relationship feature in the future.
> >
> > -Lyla
> >
> > On Sunday, April 28, 2019 at 12:46:06 PM UTC-4, Mike Bayer wrote:
> >>
> >> the next 1.3 release will include a warning for this case, whether or
> >> not the primary key on the transient object is set up or not; it does
> >> a double insert in any case otherwise.   It's just when the primary
> >> key is already present, the double insert fails on the primary key
> >> constraint.
> >>
> >> https://github.com/sqlalchemy/sqlalchemy/issues/4647
> >>
> >>
> >> On Sun, Apr 28, 2019 at 12:26 PM Mike Bayer <mik...@zzzcomputing.com>
> wrote:
> >> >
> >> > Hi there,
> >> >
> >> > I appreciate everyone chiming in to look at this!
> >> >
> >> > However, it's something simple and has to do with one of the API
> >> > quirks that we have to decide if we want to keep long term.
> >> > Background is at
> >> > https://docs.sqlalchemy.org/en/13/orm/cascades.html#backref-cascade.
> >> >
> >> > Basically, when you do this:
> >> >
> >> >     my_head = Head(id="foobar")
> >> >     my_head = db_session.merge(my_head)
> >> >     db_session.commit()
> >> >
> >> >     my_tassel_thread = TasselThread(head=my_head)
> >> >
> >> > "my_tassel_thread" is now in the Session due to the backref cascade,
> >> > which I think I really might consider defaulting to False at some
> >> > point.   it also has no primary key value yet.  So when you merge()
> >> > it, it gets put in a second time, again with no primary key.
> >> >
> >> > Another thing that makes this really bad on my part, is that if you
> >> > flush the session before the merge, then my_tassel_thread gets a new
> >> > primary key, then the merge is of itself and it works.   This is bad
> >> > because it suggests merge() should be calling flush() automatically,
> >> > but im not sure that's a good idea in the bigger scheme of things.
> >> >
> >> > Short answer, set up the relationships like:
> >> >
> >> >     tassel_threads = relationship("TasselThread",
> >> > back_populates="head", cascade_backrefs=False)
> >> >
> >> >     # ...
> >> >
> >> >     head = relationship("Head", back_populates="tassel_threads",
> >> > cascade_backrefs=False)
> >> >
> >> >
> >> > and then my_tassel_thread stays out of the Session.
> >> >
> >> > Also:
> >> >
> >> > > db_engine = create_engine('sqlite:///sample.db',
> convert_unicode=True)
> >> >
> >> > don't use convert_unicode, it's deprecated, has no purpose in the
> >> > modern Python ecosystem, and is going away.     SQLite in particular
> >> > is a fully Python unicode backend that's impossible to get a plain
> >> > string out of.
> >> >
> >> >
> >> >
> >> >
> >> > On Sun, Apr 28, 2019 at 8:56 AM <lyla...@gmail.com> wrote:
> >> > >
> >> > > Hi!
> >> > >
> >> > > I recently came across some confusing behavior in relations and
> cascading using sqllite, and I was hoping that I might get some help
> explaining what the behavior is here. I put together a minimum failing
> script here. I'm trying to commit one instance of each of two classes, but
> what ends up happening is that I commit two copies of the many part of a
> one-to-many relation. I suspect that this has something to do with
> cascading, but I found a bug report for similar behavior that claims to
> have been fixed several years ago, and I'm wondering if there was some kind
> of regression? I'm running SQLAlchemy 1.3.1 on Ubuntu and I'm still using
> sqllite at this stage of development.
> >> > >
> >> > > from sqlalchemy import create_engine
> >> > > from sqlalchemy.orm import scoped_session, sessionmaker
> >> > > from sqlalchemy.ext.declarative import declarative_base
> >> > > from sqlalchemy import Column, Integer, String, Text, ForeignKey
> >> > > from sqlalchemy.orm import relationship
> >> > >
> >> > > import os
> >> > >
> >> > > db_engine = create_engine('sqlite:///sample.db',
> convert_unicode=True)
> >> > > db_session = scoped_session(sessionmaker(autocommit=False,
> >> > >                                          autoflush=False,
> >> > >                                          bind=db_engine))
> >> > >
> >> > > Base = declarative_base()
> >> > > Base.query = db_session.query_property()
> >> > >
> >> > > class Head(Base):
> >> > >     __tablename__ = 'head'
> >> > >     id = Column(String, primary_key=True)
> >> > >     tassel_threads = relationship("TasselThread",
> back_populates="head")
> >> > >     def __init__(self, id):
> >> > >         self.id=id
> >> > >
> >> > > class TasselThread(Base):
> >> > >     __tablename__ = 'tassel_thread'
> >> > >     id = Column(Integer, primary_key=True)
> >> > >     head_id = Column(Integer, ForeignKey('head.id'),
> nullable=False)
> >> > >     head = relationship("Head", back_populates="tassel_threads")
> >> > >     def __init__(self, head):
> >> > >         self.head = head
> >> > >
> >> > > def init_db():
> >> > >     Base.metadata.create_all(bind=db_engine)
> >> > >
> >> > >
> >> > > def do_db_work():
> >> > >
> >> > >     my_head = Head(id="foobar")
> >> > >     my_head = db_session.merge(my_head)
> >> > >     db_session.commit()
> >> > >
> >> > >     my_tassel_thread = TasselThread(head=my_head)
> >> > >     db_session.merge(my_tassel_thread)
> >> > >     db_session.commit()
> >> > >
> >> > >
> >> > > if os.path.exists("sample_data.db"):
> >> > >     os.remove("sample_data.db")
> >> > > init_db()
> >> > > do_db_work()
> >> > > a = db_session.query(TasselThread).all()
> >> > > print(len(a))
> >> > > # output: 2, should be 1
> >> > >
> >> > > Thanks for any help you might be able to provide!
> >> > >
> >> > > -Lyla Fischer
> >> > >
> >> > > --
> >> > > 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 sqlal...@googlegroups.com.
> >> > > To post to this group, send email to sqlal...@googlegroups.com.
> >> > > 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.
>
> --
> 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 a topic in the
> Google Groups "sqlalchemy" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/sqlalchemy/oVVdbCzsNQg/unsubscribe.
> To unsubscribe from this group and all its topics, 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.
>

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