The Session is the ORM's single entry point for persisting and loading objects.
A Session is the ORM's workspace. It holds a connection and a transaction, tracks the objects you load or add, and writes their changes to the database.
The basic cycle:
session.add(obj)orsession.add_all([...])marks new objects as pending.session.commit()flushes pending changes as INSERT/UPDATE/DELETE statements, then commits the transaction.session.get(User, 5)loads by primary key, returningNoneif there's no such row (and returning the already-loaded object without a query if it's in the session).
Use the Session as a context manager so it's closed at the end of the block. In an application you create a factory once with SessionLocal = sessionmaker(engine) and open short-lived sessions from it, typically one per web request or job.
After commit(), by default all objects are expired: their attributes are reloaded from the database the next time you access them. That guarantees fresh data after the transaction but surprises people who access objects after closing the session. Set expire_on_commit=False on the sessionmaker when you need to return objects from a function after committing.
If something fails, session.rollback() discards the transaction; leaving the with block without committing also rolls back.
Example
from sqlalchemy import create_engine
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, sessionmaker
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
engine = create_engine("sqlite://")
Base.metadata.create_all(engine)
SessionLocal = sessionmaker(engine)
with SessionLocal() as session:
ada = User(name="ada")
session.add_all([ada, User(name="linus")])
session.commit()
print(ada.id) # 1: assigned during the flush
with SessionLocal() as session:
print(session.get(User, 2).name) # linus
print(session.get(User, 99)) # NoneRemember
- add() stages objects; commit() flushes and commits
- session.get(Model, pk) loads by primary key or returns None
- Create a sessionmaker once, open short-lived sessions from it
- Objects are expired after commit unless expire_on_commit=False
Watch out for
- Keeping one global Session for the whole application instead of one per unit of work.