Sanic¶
SQLSpec provides a Sanic extension that uses Sanic-native application and
request context. Connection pools are stored on app.ctx during the worker
lifecycle, and request-scoped connections and sessions are stored on
request.ctx.
Installation¶
Install SQLSpec with the Sanic extra:
uv add "sqlspec[sanic]"
pip install "sqlspec[sanic]"
poetry add "sqlspec[sanic]"
pdm add "sqlspec[sanic]"
Basic Setup¶
Create a SQLSpec instance, register your database config, and attach
SQLSpecPlugin to your Sanic app. Configure Sanic-specific options under
extension_config["sanic"].
sanic basic setup¶from sanic import Request, Sanic, response
from sanic.response import HTTPResponse
from sqlspec import SQLSpec
from sqlspec.adapters.aiosqlite import AiosqliteConfig, AiosqliteDriver
from sqlspec.extensions.sanic import SQLSpecPlugin
sqlspec = SQLSpec()
sqlspec.add_config(
AiosqliteConfig(
connection_config={"database": ":memory:"},
extension_config={"sanic": {"commit_mode": "manual", "session_key": "db"}},
)
)
db_plugin = SQLSpecPlugin(sqlspec)
app = Sanic("SQLSpecSanicBasicExample")
@app.get("/health")
async def health(request: Request) -> HTTPResponse:
db: AiosqliteDriver = db_plugin.get_session(request, "db")
result = await db.execute("select 1 as ok")
return response.json(result.one())
db_plugin.init_app(app)
Transaction Modes¶
Sanic supports the same transaction modes as the other request-oriented framework integrations:
manualSQLSpec manages connection scope only. Your handler commits or rolls back.
autocommitSQLSpec commits 2xx responses and rolls back other responses.
autocommit_include_redirectSQLSpec commits 2xx and 3xx responses and rolls back other responses.
Extra commit and rollback statuses are configured per database config.
sanic commit modes¶from sanic import Request, Sanic, response
from sanic.response import HTTPResponse
from sqlspec import SQLSpec
from sqlspec.adapters.aiosqlite import AiosqliteConfig
from sqlspec.extensions.sanic import SQLSpecPlugin
sqlspec = SQLSpec()
sqlspec.add_config(
AiosqliteConfig(
connection_config={"database": "app.db"},
extension_config={
"sanic": {"commit_mode": "autocommit", "extra_rollback_statuses": {409}, "session_key": "db"}
},
)
)
db_plugin = SQLSpecPlugin(sqlspec)
app = Sanic("SQLSpecSanicCommitModesExample")
@app.post("/users")
async def create_user(request: Request) -> HTTPResponse:
db = db_plugin.get_session(request, "db")
await db.execute("insert into users (name) values (:name)", {"name": request.json["name"]})
return response.json({"created": True}, status=201)
db_plugin.init_app(app)
Multiple Databases¶
For multiple databases, give each config unique connection_key,
pool_key, and session_key values. The plugin can then look up sessions
by session key.
sanic multi database¶from sanic import Request, Sanic, response
from sanic.response import HTTPResponse
from sqlspec import SQLSpec
from sqlspec.adapters.aiosqlite import AiosqliteConfig, AiosqliteDriver
from sqlspec.adapters.sqlite import SqliteConfig, SqliteDriver
from sqlspec.extensions.sanic import SQLSpecPlugin
sqlspec = SQLSpec()
sqlspec.add_config(
AiosqliteConfig(
bind_key="primary",
connection_config={"database": "primary.db"},
extension_config={
"sanic": {
"connection_key": "primary_connection",
"pool_key": "primary_pool",
"session_key": "primary_db",
}
},
)
)
sqlspec.add_config(
SqliteConfig(
bind_key="analytics",
connection_config={"database": "analytics.db"},
extension_config={
"sanic": {
"connection_key": "analytics_connection",
"pool_key": "analytics_pool",
"session_key": "analytics_db",
}
},
)
)
db_plugin = SQLSpecPlugin(sqlspec)
app = Sanic("SQLSpecSanicMultiDatabaseExample")
@app.get("/report")
async def report(request: Request) -> HTTPResponse:
primary: AiosqliteDriver = db_plugin.get_session(request, "primary_db")
analytics: SqliteDriver = db_plugin.get_session(request, "analytics_db")
users = await primary.select("select 1 as id, 'Alice' as name")
metrics = analytics.select("select 'active_users' as name, 100 as value")
return response.json({"users": users, "metrics": metrics})
db_plugin.init_app(app)
Request Access¶
Use plugin.get_session(request, key=None) for driver sessions and
plugin.get_connection(request, key=None) for raw connection access. The
default key is the first registered config's session_key; passing a key is
recommended when an app has multiple configs.
get_connection_from_request(request, config_state) and
get_or_create_session(request, config_state) are lower-level helpers for
custom integrations.
disable_di¶
Set disable_di=True when another dependency injection system owns
request-scoped connection management. SQLSpec still creates and closes pools
on Sanic startup and shutdown, but it does not put connections or sessions on
request.ctx.
sanic disable di¶from sanic import Request, Sanic, response
from sanic.response import HTTPResponse
from sqlspec import SQLSpec
from sqlspec.adapters.aiosqlite import AiosqliteConfig
from sqlspec.extensions.sanic import SQLSpecPlugin
sqlspec = SQLSpec()
config = AiosqliteConfig(
connection_config={"database": "app.db"},
extension_config={"sanic": {"disable_di": True, "pool_key": "db_pool"}},
)
sqlspec.add_config(config)
db_plugin = SQLSpecPlugin(sqlspec)
app = Sanic("SQLSpecSanicDisableDIExample")
@app.get("/health")
async def health(request: Request) -> HTTPResponse:
async with config.provide_connection(request.app.ctx.db_pool) as connection:
db = config.driver_type(connection=connection, statement_config=config.statement_config)
result = await db.execute("select 1 as ok")
return response.json(result.one())
db_plugin.init_app(app)
Correlation IDs and SQLCommenter¶
Set enable_correlation_middleware=True to extract request correlation IDs
from headers and return X-Correlation-ID on the response. The active value
is also available from request.ctx.correlation_id and
CorrelationContext during the request.
SQLCommenter is enabled when the driver StatementConfig has
enable_sqlcommenter=True and the Sanic config keeps
enable_sqlcommenter_middleware=True. Request attributes include
framework="sanic", route, and action.
sanic observability¶from sanic import Request, Sanic, response
from sanic.response import HTTPResponse
from sqlspec import SQLSpec
from sqlspec.adapters.aiosqlite import AiosqliteConfig
from sqlspec.core import StatementConfig
from sqlspec.extensions.sanic import SQLSpecPlugin
sqlspec = SQLSpec()
sqlspec.add_config(
AiosqliteConfig(
connection_config={"database": "app.db"},
statement_config=StatementConfig(enable_sqlcommenter=True),
extension_config={
"sanic": {
"enable_correlation_middleware": True,
"enable_sqlcommenter_middleware": True,
"session_key": "db",
}
},
)
)
db_plugin = SQLSpecPlugin(sqlspec)
app = Sanic("SQLSpecSanicObservabilityExample")
@app.get("/health")
async def health(request: Request) -> HTTPResponse:
return response.json({"correlation_id": request.ctx.correlation_id})
db_plugin.init_app(app)