Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check whether SQLAlchemy session is dirty or not

I have a SQLAlchemy Session object and would like to know whether it is dirty or not. The exact question what I would like to (metaphorically) ask the Session is: "If at this point I issue a commit() or a rollback(), the effect on the database is the same or not?".

The rationale is this: I want to ask the user wether he wants or not to confirm the changes. But if there are no changes, I would like not to ask anything. Of course I may monitor myself all the operations that I perform on the Session and decide whether there were modifications or not, but because of the structure of my program this would require some quite involved changes. If SQLAlchemy already offered this opportunity, I'd be glad to take advantage of it.

Thanks everybody.

like image 942
Giovanni Mascellani Avatar asked Apr 27 '13 20:04

Giovanni Mascellani


People also ask

What is Session flush in SQLAlchemy?

session. flush() communicates a series of operations to the database (insert, update, delete). The database maintains them as pending operations in a transaction.

What is Sessionmaker in SQLAlchemy?

Python Flask and SQLAlchemy ORM In order to interact with the database, we need to obtain its handle. A session object is the handle to database. Session class is defined using sessionmaker() – a configurable session factory method which is bound to the engine object created earlier. from sqlalchemy.

What does Session refresh do SQLAlchemy?

The Session will begin a new transaction if it is used again, subsequent to the previous transaction ending; from this it follows that the Session is capable of having a lifespan across many transactions, though only one at a time.

What is expunge SQLAlchemy?

You need to remove the SQL ALchemy object from the session aka 'expunge' it. Then you can request any already loaded attribute w/o it attempting to reuse its last known session/unbound session. self.expunge(record) Be aware though, that any unloaded attribute will return it's last known value or None.


2 Answers

you're looking for a net count of actual flushes that have proceeded for the whole span of the session's transaction; while there are some clues to whether or not this has happened (called the "snapshot"), this structure is just to help with rollbacks and isn't strong referencing. The most direct route to this would be to track "after_flush" events, since this event only emits if flush were called and also that the flush found state to flush:

from sqlalchemy import event
import weakref
transactions_with_flushes = weakref.WeakSet()

@event.listens_for(Session, "after_flush")
def log_transaction(session, flush_context):
    for trans in session.transaction._iterate_parents():
        transactions_with_flushes.add(trans)

def session_has_pending_commit(session):
    return session.transaction in transactions_with_flushes

edit: here's an updated version that's a lot simpler:

from sqlalchemy import event

@event.listens_for(Session, "after_flush")
def log_transaction(session, flush_context):
    session.info['has_flushed'] = True

def session_has_pending_commit(session):
    return session.info.get('has_flushed', False)
like image 110
zzzeek Avatar answered Sep 21 '22 15:09

zzzeek


The session has a dirty attribute

session.dirty

persistent objects which currently have changes detected (this collection is now created on the fly each time the property is called)

sqlalchemy.orm.session.Session.dirty

like image 37
Yoriz Avatar answered Sep 20 '22 15:09

Yoriz