Search code examples
pythontransactionssqlalchemycontextmanager

How to use SQLAlchemy contextmanager and still get row ID?


I am using SQLAlchemy's provided contextmanager to handle sessions for me. What I don't understand is how to get the automatically generated ID because (1) the ID is not created until after commit() is called yet (2) the newly created instance is only available in the context manager's scope:

def save_soft_file(name, is_geo=False):
    with session_scope() as session:
        soft_file = models.SoftFile(name=name, is_geo=is_geo)
        session.add(soft_file)
        # id is not available here, because the session has not been committed
    # soft_file is not available here, because the session is out of context
    return soft_file.id

What am I missing?


Solution

  • Use session.flush() to execute pending commands within the current transaction.

    def save_soft_file(name, is_geo=False):
        with session_scope() as session:
            soft_file = models.SoftFile(name=name, is_geo=is_geo)
            session.add(soft_file)
            session.flush()
            return soft_file.id
    

    If an exception occurs after a flush but before the session goes out of scope, the changes will be rolled back to the beginning of the transaction. In that case your soft_file would not actually be written to the database, even though it had been given an ID.