I'm building a pyramid application using pyramid_tm and ZopeTransactionExtension. We've written a little subscriber on NewResponse that writes out some values to a log file about the current user (request.user.id) after each request. For anybody that knows pyramid pretty well, we set the request.user property using config.set_request_property(get_user, 'user', reify=True), but basically we look up the User object once in our db and then cache it as request.user for the lifetime of the request.
For the most part this is working fine, except for in the case that the User object gets modified during the request (change their avatar, name, password, whatever). When this happens, we get a Detached Instance exception when we try to reference the 'id' field of request.user. It's worth pointing out that pyramid_tm runs and commits our transaction before our NewResponse subscriber fires, which means that request.user has already been flushed and committed to the database and appears to be detached (in fact, we can merge it back into our session and continue using it as normal, see Solution #3 below). We've found 3 work-arounds that seem to give us the desired behavior, but I'm not really sure which one is better. Solution 1 ---------- # setting up the session DBSession = scoped_session(sessionmaker(bind=engine, extension=ZopeTransactionExtension(), expire_on_commit=False)) # in the subscriber print request.user.id # does 0 additional db queries Solution 2 ---------- # setting up the session DBSession = scoped_session(sessionmaker(bind=engine, extension=ZopeTransactionExtension(keep_session=True))) # in the subscriber print request.user.id # does an additional SELECT query Solution 3 ---------- # setting up the session DBSession = scoped_session(sessionmaker(bind=engine, extension=ZopeTransactionExtension())) # in the subscriber session = DBSession() user = session.merge(request.user) # does an additional SELECT query print user.id Without using any of these solutions, we sure enough get the Exception: DetachedInstanceError: Instance <User at 0x26d5990> is not bound to a Session; attribute refresh operation cannot proceed In this case, it seems Solution 1 is the best as it doesn't do any additional SQL queries (and I'm willing to accept that occasionally I might be writing a stale User object to disk), but is there any other downside to this approach? After my subscriber runs the web request is finished, so theoretically it doesn't matter that the objects are not expired, correct? Is there a better approach here that I am missing? Thanks! -- 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 http://groups.google.com/group/sqlalchemy?hl=en. For more options, visit https://groups.google.com/groups/opt_out.