Skip to content

Getting Started

A complete example from scratch using SQLModel. The approach is the same for SQLAlchemy and Tortoise — see ORM Adapters.

Installation

pip install "fastapi-crud-generator[sqlmodel]"
pip install aiosqlite  # or asyncpg for PostgreSQL

Model

from sqlmodel import Field, SQLModel

class Article(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    title: str
    content: str
    published: bool = False

No Pydantic schemas needed — they are generated automatically.

Session

from sqlalchemy.ext.asyncio import create_async_engine
from sqlmodel.ext.asyncio.session import AsyncSession
from collections.abc import AsyncGenerator

engine = create_async_engine("sqlite+aiosqlite:///db.sqlite3")

async def get_session() -> AsyncGenerator[AsyncSession, None]:
    async with AsyncSession(engine) as session:
        yield session

Wiring up CRUD

from fastapi import FastAPI
from fastapi_crud_generator import CRUDCollection
from fastapi_crud_generator.orm.sqlmodel import SQLModelAdapter

app = FastAPI()

crud = CRUDCollection(
    orm_adapter=SQLModelAdapter(model=Article, get_session=get_session),
)
app.include_router(crud.get_router(prefix="/articles", tags=["articles"]))

What you get

Five endpoints with full OpenAPI docs at /docs:

Method URL Body Response
GET /articles { page, per_page, count, data: [...] }
GET /articles/{article_id} article object
POST /articles { title, content, published } created object
PATCH /articles/{article_id} any fields (all optional) null
DELETE /articles/{article_id} deleted object

Schemas

The adapter decides which fields go into each schema:

  • public (GET responses) — all model fields including id
  • create (POST) — all fields except id (generated by the database)
  • update (PATCH) — same fields as create, but all optional

Filtering

GET /articles?published=true
GET /articles?title=hello

Sorting

GET /articles?sort=title
GET /articles?sort=title:desc
GET /articles?sort=title:asc&sort=published:desc

Pagination

GET /articles?page=2&per_page=5
{
  "page": 2,
  "per_page": 5,
  "count": 42,
  "data": [...]
}

Next steps