Sessions¶
A SQLAlchemy sessionmaker is created when
SQLAlchemy.init_app() is called. Both sync and async sessionmakers
are created regardless of if any sync or async engines are defined.
Default Options¶
Default session options can be passed as the session_options parameter when
creating the SQLAlchemy instance. This applies to both sync and async
sessions. You can call each sessionmaker’s configure method if you need
different options for each.
Session Management¶
Most use cases will use one session, and tie it to the lifetime of each request.
Use db.session for this. It will return the same
session throughout a request, then close it when the request ends. SQLAlchemy
will rollback any uncomitted state in the session when it is closed.
You can also create other sessions besides the default. Calling
db.get_session(name) will create separate
sessions that are also closed at the end of the request.
The sessions are closed when the application context is torn down. This happens
for each request, but also at the end of CLI commands, and for manual
with app.app_context() blocks.
Manual Sessions¶
You can also use db.sessionmaker directly to
create sessions. These will not be closed automatically at the end of requests,
so you’ll need to manage them manually. An easy way to do that is using a with
block.
with db.sessionmaker() as session:
...
Async¶
SQLAlchemy warns that the async sessions it provides are not safe to be used
across concurrent tasks. For example, the same session should not be passed to
multiple tasks when using asyncio.gather. Either use
db.get_async_session(name) with a unique
name for each task, or use
db.async_sessionmaker to manage session
lifetimes manually. The latter is what SQLAlchemy recommends.
Multiple Binds¶
If the "default" engine key is defined when initializing the extension, it
will be set as the default bind for sessions. This is optional, but if you don’t
configure it up front, you’ll want to call db.sessionmaker.configure(bind=...)
later to set the default bind, or otherwise specify a bind for each query.
SQLAlchemy supports using different engines when querying different tables or
models. This requires specifying a mapping from a model, base class, or table to
an engine object. When using the extension, you can set this up generically
in session_options by mapping to names instead of engine objects. During
initialization, the extension will substitute each name for the configured
engine. You can also call db.sessionmaker.configure(binds=...) after the fact
and pass the engines using get_engine() yourself.
db = SQLAlchemy(session_options={"binds": {
User: "auth",
Role: "auth",
ExternalBase: "external",
}})