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.

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) None#

Configure FastAPI-Restly. Call once at startup.

Pass async parameters (async_database_url, async_engine, or async_make_session) to enable async support, sync parameters (database_url, engine, or make_session) for sync support, or both if your application uses both.

A test suite that calls fastapi_restly.testing.configure_tests() freezes these database sources for the rest of that pytest process. Select the test settings and configure the application before enabling managed testing; changing database sources afterwards would make schema setup, cleanup, and requests disagree and therefore raises.

Use session_generator / sync_session_generator (or engine / make_session) to construct sessions your way – a custom engine, isolation level, search_path, logging, an existing sessionmaker. A custom generator’s job is to construct, yield, and clean up (close / roll back on the way out); it must not commit. Customizing how a session is built never takes the commit away from Restly.

Restly owns the commit. Every write – the CRUD handlers (handle_create / handle_update / handle_delete) and write_action – runs before_commit -> commit -> after_commit around your domain logic; the commit is the framework’s single responsibility. A custom (non-CRUD) write route either brackets its mutation with write_action(...) (recommended) or commits the session itself with await self.session.commit().

By default Restly warns (RestlyUncommittedChangesWarning) when a request finishes with uncommitted changes still in the session – the tell of a custom write route that forgot to commit. This applies to every session source, built-in or custom. A route that intentionally leaves a flush uncommitted (a validate-then-rollback dry run) should suppress the warning for just that request with session.info["_fr_suppress_uncommitted"] = True. warn_on_uncommitted=False turns the check off globally; that is rarely the right response to the warning – prefer fixing the missing commit or the per-route suppression.

Pass warn_on_misuse=True to enable opt-in registration-time misuse warnings (RestlyMisuseWarning): when a view class is registered via include_view, the framework flags route-shell overrides, direct session.commit() calls in view methods, CRUD route sets hand-rolled on a bare View, and scalar foreign-key columns typed as an IDRef / IDSchema reference instead of fr.MustExist. Off by default; intended for development, templates, and CI. Enable it before registering views.

Pass your FastAPI app to install fastapi-restly’s default exception handlers (currently: a translator that turns SQLAlchemy IntegrityError into HTTP 409 Conflict). Set install_default_exception_handlers=False to opt out. If you do not pass app here, the handlers are registered the first time a view is mounted via fastapi_restly.include_view() instead.

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 fastapi_restly.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 fastapi_restly.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.