ORM Adapters¶
fastapi-viewsets doesn't bundle database drivers — you pick them per stack. The library reads configuration from environment variables (loaded via python-dotenv from .env). Pick the ORM with ORM_TYPE, then set the URL with <ORM>_DATABASE_URL (or the generic DATABASE_URL).
Supported ORMs¶
| ORM | Sync | Async | Extra |
|---|---|---|---|
| SQLAlchemy | ✅ BaseViewset |
✅ AsyncBaseViewset |
[sqlalchemy] |
| Tortoise ORM | — | ✅ AsyncBaseViewset |
[tortoise] |
| Peewee | ✅ BaseViewset |
— | [peewee] |
Database driver matrix¶
| ORM | PostgreSQL | MySQL | MSSQL |
|---|---|---|---|
| SQLAlchemy (sync) | psycopg[binary] or psycopg2-binary |
pymysql or mysqlclient |
pyodbc + ODBC Driver 17/18 |
| SQLAlchemy (async) | asyncpg |
aiomysql or asyncmy |
aioodbc + ODBC Driver 17/18 |
| Tortoise ORM | asyncpg (included in [tortoise] extra) |
aiomysql (install separately) |
Not supported by Tortoise |
| Peewee | psycopg2-binary |
pymysql or mysqlclient |
Not supported by this adapter |
Auto sync-to-async URL conversion
The SQLAlchemyAdapter auto-converts a sync URL to its async counterpart:
postgresql://→postgresql+asyncpg://mysql://→mysql+aiomysql://sqlite:///→sqlite+aiosqlite:///
For MSSQL you must set the async URL explicitly via SQLALCHEMY_ASYNC_DATABASE_URL. If the matching async driver is not installed, SQLAlchemyAdapter falls back to sync-only mode and get_async_session() raises a helpful RuntimeError (since v1.2.1).
SQLAlchemy (sync and async)¶
PostgreSQL¶
MySQL¶
MSSQL¶
Requires Microsoft ODBC Driver 17 or 18 on the host:
.env examples¶
ORM_TYPE=sqlalchemy
# URL-encode the ODBC driver name ("+" instead of spaces).
SQLALCHEMY_DATABASE_URL=mssql+pyodbc://user:pass@db.example.com:1433/app?driver=ODBC+Driver+18+for+SQL+Server&Encrypt=yes&TrustServerCertificate=no
SQLALCHEMY_ASYNC_DATABASE_URL=mssql+aioodbc://user:pass@db.example.com:1433/app?driver=ODBC+Driver+18+for+SQL+Server&Encrypt=yes&TrustServerCertificate=no
Use BaseViewset for sync code or AsyncBaseViewset for async code — see Sync Quickstart and Async Quickstart.
Tortoise ORM¶
Tortoise is async-only. The adapter takes a database URL plus a list of model modules to register on startup.
# PostgreSQL
pip install "fastapi-viewsets[tortoise]" # pulls in asyncpg
# MySQL
pip install "fastapi-viewsets[tortoise]" aiomysql
.env examples¶
Usage¶
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi_viewsets import AsyncBaseViewset
from fastapi_viewsets.orm.factory import ORMFactory
adapter = ORMFactory.get_default_adapter() # built from the env vars above
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Open the Tortoise connection pool at startup.
The adapter also initialises Tortoise lazily on the first DB call,
but calling ``initialize()`` here gives you control over schema creation
and avoids a cold-start penalty on the first request.
"""
await adapter.initialize(generate_schemas=True)
yield
await adapter.close()
app = FastAPI(lifespan=lifespan)
# Define your Tortoise models in app/models.py and pass them to AsyncBaseViewset.
# from app.models import Item
# from app.schemas import ItemSchema
# items = AsyncBaseViewset(
# endpoint="/items",
# model=Item,
# response_model=ItemSchema,
# db_session=adapter.get_async_session,
# orm_adapter=adapter,
# tags=["items"],
# )
# items.register(methods=["LIST", "GET", "POST", "PATCH", "DELETE"])
# app.include_router(items)
Production schema management
generate_schemas=True is convenient for development. In production, use
Aerich or another migration tool
instead of auto-generating schemas at startup.
MSSQL not supported
MSSQL is not supported by Tortoise ORM. Use SQLAlchemy with aioodbc for SQL Server.
Peewee¶
Peewee is sync-only. The adapter parses the URL and instantiates the right Database class.
# PostgreSQL
pip install "fastapi-viewsets[peewee]" psycopg2-binary
# MySQL
pip install "fastapi-viewsets[peewee]" pymysql
.env examples¶
Usage¶
from fastapi import FastAPI
from fastapi_viewsets import BaseViewset
from fastapi_viewsets.orm.factory import ORMFactory
app = FastAPI()
adapter = ORMFactory.get_default_adapter() # built from the env vars above
# from app.models import Item # peewee.Model subclass
# from app.schemas import ItemSchema # Pydantic v2 schema
# items = BaseViewset(
# endpoint="/items",
# model=Item,
# response_model=ItemSchema,
# db_session=adapter.get_session,
# orm_adapter=adapter,
# tags=["items"],
# )
# items.register(methods=["LIST", "GET", "POST", "PATCH", "DELETE"])
# app.include_router(items)
MSSQL not supported
The Peewee adapter only handles sqlite:///, postgresql://, postgres://, and mysql://. For SQL Server, use SQLAlchemy.
Building the adapter from code (no env vars)¶
When you don't want to rely on environment variables, instantiate the adapter directly and pass it to the viewset via orm_adapter=:
from fastapi_viewsets.orm.factory import ORMFactory
adapter = ORMFactory.create_adapter(
"sqlalchemy",
{
"database_url": "postgresql+psycopg://user:pass@db.example.com:5432/app",
"async_database_url": "postgresql+asyncpg://user:pass@db.example.com:5432/app",
},
)
This is useful for testing, multi-tenant setups, or when configuration comes from a secrets manager rather than .env.
The ORMFactory class¶
The ORMFactory is the central entry point for adapter resolution:
| Method | Returns | Description |
|---|---|---|
ORMFactory.get_default_adapter() |
BaseORMAdapter |
Returns the cached singleton adapter for the current ORM_TYPE |
ORMFactory.create_adapter(orm_type, config) |
BaseORMAdapter |
Creates a new adapter instance from a dict config |
All adapters implement the BaseORMAdapter abstract interface — see API Reference for the full method list.