Database API#

fastapi_restly.db implements the connection layer: configure() for process-wide setup, session context managers and FastAPI session dependencies, engine accessors, table creation helpers for development, and the savepoint-only mode used in testing.

fastapi_restly.db.AsyncSessionDep#

Annotated alias that supplies a SQLAlchemy AsyncSession through FastAPI dependency injection. The session uses the configuration set by configure().

fastapi_restly.db.SessionDep#

Annotated alias that supplies a SQLAlchemy Session through FastAPI dependency injection. The session uses the configuration set by configure().

async fastapi_restly.db.async_create_all(base_or_metadata: type[DeclarativeBase] | MetaData) → None#

Async equivalent of create_all(), on the configured async engine.

Usage:

await fr.db.async_create_all(Base)
fastapi_restly.db.configure(app: FastAPI | None = None, *, async_database_url: str | None = None, async_engine: AsyncEngine | None = None, async_make_session: async_sessionmaker[Any] | None = None, database_url: str | None = None, engine: Engine | None = None, make_session: sessionmaker[Any] | None = None, session_generator: Callable[[...], AsyncIterator[AsyncSession]] | None = None, sync_session_generator: Callable[[...], Iterator[Session]] | None = None, warn_on_misuse: bool | None = None, warn_on_uncommitted: bool | None = None, install_default_exception_handlers: bool = True, health: str | None = None) → None#

Configure FastAPI-Restly. Call once at startup.

Async support comes from async_database_url, async_engine, or async_make_session; sync support from database_url, engine, or make_session. Pass both sets if the application uses both.

A URL is the one form Restly builds an engine from, and that engine gets defaults suited to a web application: StaticPool for in-memory SQLite, PRAGMA foreign_keys=ON on every SQLite connection, and pool_pre_ping with pool_recycle on PostgreSQL. Pool sizing is left alone, and so is anything written into the database itself, which is why journal_mode=WAL is not among them. Every other form is used as given, so passing engine= declines all of this.

Restly owns the commit: the CRUD handlers and write_action run before_action_commit -> commit -> after_action_commit around your domain logic. A custom session generator constructs, yields, and cleans up, and must not commit. A custom write route brackets its mutation with write_action(...) or commits the session itself.

Configure custom generators before registering routes that use SessionDep or AsyncSessionDep. FastAPI resolves the generator as a sub-dependency, sharing its cached session with the application’s Depends(get_db). Explicit view dependencies remain as declared. Generators used outside a request through open_session() or open_async_session() must be callable without arguments.

fastapi_restly.testing.configure_tests() freezes the database sources for the rest of that pytest process, so configure the application before enabling managed testing; changing them afterwards raises.

Parameters:
  • app – Application to install the default exception handlers and the health route on. Restly also checks its OpenAPI spec for two classes with the same name (see RestlyDuplicateSchemaNameWarning).

  • async_database_url – Async URL to build an AsyncEngine from.

  • async_engine – Async engine to use as given.

  • async_make_session – async_sessionmaker to use as given.

  • database_url – Sync URL to build an Engine from.

  • engine – Sync engine to use as given.

  • make_session – sessionmaker to use as given.

  • session_generator – Callable yielding the AsyncSession for each request.

  • sync_session_generator – Callable yielding the Session for each request.

  • warn_on_misuse – Emit RestlyMisuseWarning when include_view registers a view with an endpoint method override, a direct session.commit(), a hand-rolled CRUD route set on a bare View, or a scalar foreign key typed as an IDRef / IDSchema reference instead of fr.MustExist. Off by default; set it before registering views.

  • warn_on_uncommitted – Emit RestlyUncommittedChangesWarning when a request finishes with uncommitted changes. On by default. Suppress one deliberate case with session.info["_fr_suppress_uncommitted"] = True rather than turning the check off.

  • install_default_exception_handlers – Install the translator that turns IntegrityError into HTTP 409. On by default. Without app, the first include_view() installs them instead.

  • health – Path to mount a liveness endpoint on, such as "/health". It answers 200 with {"status": "ok"}, appears in the OpenAPI schema, and makes no database round-trip. Off unless set, and requires app. A route already mounted at that path is left in place. Readiness is a separate endpoint of your own, not a mode of this one.

Raises:
  • TypeError – No setup argument was given.

  • RestlyConfigurationError – health is not an absolute path or was passed without app, a generator changed after route registration, or the database configuration changed after configure_tests() recorded it.

fastapi_restly.db.create_all(base_or_metadata: type[DeclarativeBase] | MetaData) → None#

Create all tables for base_or_metadata on the configured sync engine.

A dev/demo convenience over metadata.create_all(engine) so a quickstart can create its schema without reaching for the raw engine:

fr.db.create_all(Base)  # or fr.db.create_all(Base.metadata)

Accepts a DeclarativeBase subclass (its .metadata is used) or a MetaData. Requires configure() first. Use Alembic migrations in production.

fastapi_restly.db.get_async_engine() → AsyncEngine#

Return the async engine registered via configure().

fastapi_restly.db.get_engine() → Engine#

Return the sync engine registered via configure().

fastapi_restly.db.open_async_session() → AsyncGenerator[AsyncSession]#

Open an async database session for use outside of request context.

Resolves the same source as AsyncSessionDep: a custom session_generator passed to configure() if one is configured, otherwise the built-in async session factory. (The request-only uncommitted-changes check is not armed here – off-HTTP code owns its commit, exactly as a custom write route does.)

In a managed test this yields a session from the test’s isolated factory, even when no public session or client fixture is requested.

Example:

async with fr.open_async_session() as session:
    result = await session.execute(select(User))
fastapi_restly.db.open_session() → Generator[Session]#

Open a sync database session for use outside of request context.

Resolves the same source as SessionDep: a custom sync_session_generator passed to configure() if one is configured, otherwise the built-in sync session factory. (The request-only uncommitted-changes check is not armed here – off-HTTP code owns its commit, exactly as a custom write route does.)

In a managed test this yields a session from the test’s isolated factory, even when no public session or client fixture is requested.

Example:

with fr.open_session() as session:
    result = session.execute(select(User))

See also

Use Restly in an Existing Project shows how to wire Restly into existing engines and sessions, and Deploying covers production engine configuration.