On Aug 26, 2010, at 8:49 AM, Martin-Leon Francois wrote: > hi, > > The problem seems to be a little bit more general, I have a unique class > (doing nothing) mapped to a unique table. > After opening a session, I create an instance, add it to the session, flush, > commit. > Everything is ok. --> a row in the table, instance in the identity_map of the > session > > Always in the same session, I delete the instance from the session., flush, > commit. > Everything is ok. --> no row in the table, no instance in the identity_map > of the session > > Always the same session, I add again the python instance to the session, > flush, commit. > ??? --> no row in the table, instance in the identity_map of the session > > Could you have a look to the code below and help me figure out what I doing > wrong? > fma > > #If I uncomment the following line (workaround) instance is written down to > #the database as I would expect > #o1._sa_instance_state = o1._sa_class_manager._create_instance_state(o1) > > s.add(o1) > s.add_all([o1]) > s.flush() > s.commit() > print list(s.query(One)), s.identity_map > s.close()
OK this is a little strange. o1 has been deleted. You've found one particular operation that doesn't immediately raise (add()), but anything else you did with o1 would, for example: print o1.name you will get this (since o1 is expired and will refresh, then fail): sqlalchemy.orm.exc.ObjectDeletedError: Instance '<One at 0x1288c70>' has been deleted. as you've already figured out, o1 has state on it that tells SQLAlchemy that this object is already persistent - no INSERT will be executed again for the object. The strange part here is that the object is beyond persistent and is in the deleted state, and we don't have an in-memory flag that would signal this, though perhaps that is called for here, I've never seen anyone trying to perform such an operation before. Anyway to convert from persistent back to transient, use make_transient: from sqlalchemy.orm import make_transient make_transient(o1) then the "key" is removed and the object is as though you just created it. I want to check if there's some foolproof way we can block on add(). Also, the add()/add_all() calls are redundant as is the flush() right before the commit(). > > Le 26 août 2010 à 08:42, fma a écrit : > >> Any suggestion helping solving this? >> >> On 25 août, 13:02, Martin-Leon Francois <francois....@gmail.com> >> wrote: >>> Hi, >>> >>> I am trying in the same session to detach an instance from a collection ( >>> one to many) >>> flush and commit everything (all is ok) and then attach the removed >>> instance again. unsuccessfully. >>> >>> in below code, last "assert" fails. >>> I don't understand why I am not able to append m2 to o1.to_many collection >>> once removed. >>> >>> Any idea? ( I use sa 0.5.6) >>> >>> thanx, Francois >>> >>> meta = MetaData() >>> tb_one = Table("one", meta, >>> Column('name',String(50)), >>> Column('id',Integer, primary_key=True)) >>> >>> tb_many = Table("many", meta, >>> Column('name',String(50)), >>> Column('id',Integer, primary_key=True), >>> Column('one_id', Integer, >>> ForeignKey(tb_one.c.id,ondelete='CASCADE'), nullable=False),) >>> >>> class One(object): >>> def __init__(self, name): >>> self.name = name >>> >>> class Many(object): >>> def __init__(self, name): >>> self.name = name >>> >>> mapper_one = mapper(One,tb_one) >>> mapper_many = mapper(Many, tb_many, >>> properties = dict( >>> to_one = relation(One,uselist=False, >>> backref=backref('to_many', cascade="save-update, merge, delete, >>> delete-orphan"),))) >>> >>> engine = create_engine(....) >>> Session = orm.sessionmaker(autoflush=True, autocommit=False, bind=engine) >>> >>> meta.bind = engine >>> meta.drop_all(checkfirst=True) >>> meta.create_all(checkfirst=True) >>> >>> s = Session() >>> m1 = Many("M1") >>> m2 = Many("M2") >>> o1 = One("One") >>> o1.to_many.append(m1) >>> o1.to_many.append(m2) >>> >>> s.add_all([m1,m2,o1]) >>> s.flush() >>> s.commit() >>> assert(len(o1.to_many) == 2) >>> >>> o1.to_many.remove(m2) >>> assert(len(o1.to_many) == 1) >>> s.flush() >>> s.commit() >>> assert(len(o1.to_many) == 1) >>> >>> o1.to_many.append(m2) >>> assert(len(o1.to_many) == 2) >>> s.flush() >>> s.commit() >>> assert(len(o1.to_many) == 2) #this assert fails why? >>> >>> s.close() >> >> -- >> You received this message because you are subscribed to the Google Groups >> "sqlalchemy" group. >> To post to this group, send email to sqlalch...@googlegroups.com. >> To unsubscribe from this group, send email to >> sqlalchemy+unsubscr...@googlegroups.com. >> For more options, visit this group at >> http://groups.google.com/group/sqlalchemy?hl=en. >> > > > -- > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > To post to this group, send email to sqlalch...@googlegroups.com. > To unsubscribe from this group, send email to > sqlalchemy+unsubscr...@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/sqlalchemy?hl=en. -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalch...@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.