On Jan 31, 4:33 am, Michael Bayer <[email protected]> wrote:
> this example is too compliated for me to understand without great effort,
> perhaps someone else has the time to follow it more closely - it appears to
> be creating and closing many new sessions and add()ing objects between them -
> an unusual series of events.
My use case is this: I am writing a framework that allows you to
create and update objects over a series of requests, stashing the
object in the session between requests. I undersood this to be one of
the supported use-cases of SQLAlchemy.
So the general sequence of events is:
1. create or load object, don't flush, and detach
2. reattach object, modify, don't flush and detach
3. repeat 2 as necessary
4. when ready, reattach object and commit
I had previously used merge(), but that causes too much database
chatter and slows things down considerably. dont_load doesn't support
"dirty" objects. So I saw that add() can reattach a detached instance
to a session, and it all appears to work as expected (namely changing
attributes and adding/changing child relations) *except* child
deletions.
I hope that is clearer.
Actually, I just tried it against 0.6 trunk and this script works. It
doesn't work in 0.5 (r6712)
Sorry about clagging inline, google groups doesn't have an attachment
facility.
"""
import sqlalchemy as sql
from sqlalchemy import orm
from sqlalchemy.ext.declarative import declarative_base
engine = sql.create_engine("sqlite:///:memory:")
metadata = sql.MetaData(bind=engine)
DB = orm.sessionmaker(bind=engine)
T = declarative_base(metadata=metadata)
class A(T):
__tablename__ = 'a'
id = sql.Column(sql.Integer, primary_key=True)
info = sql.Column(sql.String)
cc = orm.relation('C',
backref='a',
cascade='all,delete-orphan')
def __repr__(self):
return " >> a: %s cc=%s" % (self.info, len(self.cc))
class C(T):
__tablename__ = 'c'
a_id = sql.Column(sql.Integer, sql.ForeignKey('a.id'),
primary_key=True)
i = sql.Column(sql.Integer, primary_key=True)
metadata.create_all()
A.__table__.delete().execute()
def get():
return DB().query(A).first()
def change_detached(a, s, i):
# attach instance to a session to operate on it
# then detach it again to store it in a session
# change and attribute, delete one child and add another
# so len(cc) is unchanged
db = DB()
db.add(a)
a.info = s
del a.cc[-1]
a.cc.append(C(i=i))
db.close()
def store(a, merge=False):
db = DB()
if merge:
db.merge(a)
else:
db.add(a)
db.commit()
db.close()
# create and store instance
store(A(id=1, info='blah', cc=[C(i=1), C(i=2)]))
assert len(get().cc) == 2 # ok
# get and detach instance
a = get()
orm.object_session(a).close()
# change 1
change_detached(a, 'change-one', 3)
# store, reattaching with merge()
store(a, True)
assert len(get().cc) == 2 # ok
# get and detach instance
a = get()
orm.object_session(a).close()
# change 2
change_detached(a, 'change-two', 4)
# store, reattaching with add()
store(a, False)
assert len(get().cc) == 2 # fails!
"""
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sqlalchemy?hl=en.