the behavior here is a product of two things: 1. you’ve disabled expire on commit:
expire_on_commit=False
2. the collection is not managed in Python because you are not mutating it,
that is you are only saying:
session.delete(dan)
and not:
peter.children.remove(dan)
Hence without the advent of Python management of the collection, nor expiring
the collection so that it can be reloaded from the database after the commit,
an inconsistency is apparent.
Having to do both session.delete() and collection.remove() would be very
tedious! hence we provide delete cascade functionality to handle this. This
feature is common enough that it has both an entire section in the ORM tutorial
as well as a dedicated section in the session documentation, please see:
http://docs.sqlalchemy.org/en/rel_0_9/orm/tutorial.html#configuring-delete-delete-orphan-cascade
http://docs.sqlalchemy.org/en/rel_0_9/orm/session.html#deleting-from-collections
On Jan 3, 2014, at 7:51 AM, pr64 <[email protected]> wrote:
> Hi,
>
> Sorry for the previous post. Attached script had a typo.
>
> When deleting a child, I would like the children list of the parent to be
> automatically updated...
>
> Am i doing something wrong or missed some configuration ?
>
> Please note that i'm using sqa 0.8.4.
>
> Thanks
>
> Pierre
>
> ----
>
> #!/usr/bin/env python
> # -*- coding: utf-8 -*-
>
> import os
> import sqlite3
> from sqlalchemy import *
> from sqlalchemy.types import *
> from sqlalchemy.orm import *
> from sqlalchemy.pool import NullPool
> from sqlalchemy.ext.declarative import declarative_base
>
> Base = declarative_base()
> METADATA = Base.metadata
> DB_NAME = "example.db"
>
> class Child(Base):
>
> __tablename__ = 'children'
> id = Column(Integer, primary_key=True)
> name = Column(String(20), nullable=False)
>
> # Many to One Child --- Parent
> parent_id = Column(Integer, ForeignKey('parent.id'))
> parent = relationship("Parent", backref="children")
>
> def __init__(self, name):
> self.name = name
>
> def __repr__(self):
> return self.name
>
> class Parent(Base):
>
> __tablename__ = 'parent'
> id = Column(Integer, primary_key=True)
> name = Column(String(20), nullable=False)
>
> def __init__(self, name):
> self.name = name
>
> def __repr__(self):
> return self.name
>
>
> if os.path.exists(DB_NAME):
> os.remove(DB_NAME)
>
> engine = create_engine('sqlite:///%s' % DB_NAME,
> connect_args={'detect_types': sqlite3.PARSE_DECLTYPES|
> sqlite3.PARSE_COLNAMES},
> poolclass=NullPool,
> )
>
> def print_family(parent):
>
> print "%s's family:" % parent
> for child in parent.children:
> print "|____ %s" % child
>
> session_maker = sessionmaker()
> METADATA.create_all(engine)
> session_maker.configure(bind=engine, expire_on_commit=False)
>
> session = session_maker()
>
> peter = Parent(name="Peter")
> dan = Child(name="Dan")
> jenny = Child(name="Jenny")
>
> peter.children.append(dan)
> peter.children.append(jenny)
>
> session.add_all([dan, jenny, peter])
> session.commit()
>
> children = session.query(Child).all()
> print children
>
> parents = session.query(Parent).all()
>
> for parent in parents:
> print_family(parent)
>
> session.delete(dan)
> session.commit()
> print "Deleted Dan !"
>
> for parent in parents:
> print_family(parent)
> print "??? Dan is still in Peter's family..."
>
> children = session.query(Child).all()
> print children
>
> print "... but not in the children list... :-("
>
>
> --
> 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 [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/groups/opt_out.
signature.asc
Description: Message signed with OpenPGP using GPGMail
