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, orasync_make_session) to enable async support, sync parameters (database_url,engine, ormake_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(orengine/make_session) to construct sessions your way – a custom engine, isolation level,search_path, logging, an existingsessionmaker. 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) andwrite_action– runsbefore_commit-> commit ->after_commitaround your domain logic; the commit is the framework’s single responsibility. A custom (non-CRUD) write route either brackets its mutation withwrite_action(...)(recommended) or commits the session itself withawait 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 withsession.info["_fr_suppress_uncommitted"] = True.warn_on_uncommitted=Falseturns 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=Trueto enable opt-in registration-time misuse warnings (RestlyMisuseWarning): when a view class is registered viainclude_view, the framework flags route-shell overrides, directsession.commit()calls in view methods, CRUD route sets hand-rolled on a bareView, and scalar foreign-key columns typed as anIDRef/IDSchemareference instead offr.MustExist. Off by default; intended for development, templates, and CI. Enable it before registering views.Pass your
FastAPIappto install fastapi-restly’s default exception handlers (currently: a translator that turns SQLAlchemyIntegrityErrorinto HTTP 409 Conflict). Setinstall_default_exception_handlers=Falseto opt out. If you do not passapphere, the handlers are registered the first time a view is mounted viafastapi_restly.include_view()instead.
- fastapi_restly.db.create_all(base_or_metadata: type[DeclarativeBase] | MetaData) None#
Create all tables for
base_or_metadataon 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
DeclarativeBasesubclass (its.metadatais used) or aMetaData. Requiresconfigure()first. Use Alembic migrations in production.
- fastapi_restly.db.get_async_engine() AsyncEngine#
Return the async 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 customsession_generatorpassed tofastapi_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 customsync_session_generatorpassed tofastapi_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.