On 04/03/2017 11:48 AM, Shane Carey wrote:
So the reason the children are marked for delete is because they are no
longer associated with the parent, and for that same reason the expunge does
not propagate to them.

As much as I wish this would work for me, I have to agree with you. Is
there any way to prevent
the delete from occurring on the autoflush? I simply need to stop all
changes to my parent
from being persisted, without rolling back the session.


you'd need to expunge (or expire, at least) those Child objects as well. You can get them from inspect(p).attrs.children.history.deleted




On Monday, April 3, 2017 at 9:47:13 AM UTC-5, Mike Bayer wrote:



    On 04/03/2017 09:52 AM, Shane Carey wrote:
    > I am getting an error where delete orphan on a relationship seems to
    > happen even when the parent object is expunged.
    >
    > I reproduced the issue in this example.
    >
    > from sqlalchemy import *
    > from sqlalchemy.orm import *
    > from sqlalchemy.ext.declarative import *
    >
    > Base = declarative_base()
    >
    > class Parent(Base):
    > __tablename__ = 'parent'
    >
    > id = Column(Integer, primary_key=True)
    >
    > children = relationship('Child', lazy='joined', backref='parent',
    > cascade='all, delete-orphan')
    >
    > def dict(self):
    > return {
    > 'id': self.id <http://self.id>,
    > 'children': [c.dict() for c in self.children]
    > }
    >
    > class Child(Base):
    > __tablename__ = 'child'
    >
    > parent_id = Column(None, ForeignKey(Parent.id), primary_key=True)
    > name = Column(String(8), primary_key=True)
    >
    > def dict(self):
    > return {
    > 'name': self.name <http://self.name>
    > }
    >
    > if __name__ == '__main__':
    > e = create_engine('sqlite:///orphan.db', echo=True)
    >
    > Base.metadata.drop_all(e)
    > Base.metadata.create_all(e)
    >
    > s = sessionmaker(e)()
    >
    > p = Parent()
    > p.children = [Child(name=str(i)) for i in range(5)]
    >
    > s.add(p)
    > s.commit()
    >
    > p = s.query(Parent).one()
    > print(p.dict())
    >
    > p.children = [Child(name=str(i)) for i in range(5, 10)]
    >
    > print(p.dict())
    >
    > s.expunge(p)
    >
    > p = s.query(Parent).one()
    > print(p.dict())
    >
    > The parent has no children after the expunge, is this intended or
    a bug?

    Hi there -

    OK, this is definitely more of a mindbender, and I don't know that
    there's a way situations like these can have a little less cognitive
    load on them.  However, let me propose an alternate form of what we see
    above - let's see if our expectations change:


    p = Parent()
    p.children = [Child(name=str(i)) for i in range(5)]

    s.add(p)
    s.commit()

    p = s.query(Parent).one()

    for child in p.children:
         child.parent = None

    for i in range(5, 10):
         Child(name=str(i), parent=p)

    s.expunge(p)


    now, with the above, for the original Child 1-5, do we expect:

    1. that they are also expunged?  Why would that be, when they are no
    longer associated with p?

    2. that they be treated as non-orphans?  Why would that be, when we
    have
    set child.parent = None?

    therefore, looking at it from the above perspective it seems to me that
    they *should* be deleted upon flush.   the flush here occurs as the
    autoflush on the next query.

    let me know if this makes sense.   I agree that initially, I asked
    myself, hmm should expunge count for Parent.collection.<deleted items>
    also, or somehow revert that change?   But looking from the perspective
    of many-to-one, which is implicit in the one-to-many operations, it
    seems like not.







    >
    > --
    > 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:>>.
    > 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+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.

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