Getting started¶
Installation¶
Using uv (recommended):
# create & activate virtual env with uv
uv venv
. .venv/bin/activate
# add runtime dependency
uv add fastapi-fsp
Using pip:
pip install fastapi-fsp
Quick start¶
Below is a minimal example using FastAPI and SQLModel.
from typing import Optional
from fastapi import Depends, FastAPI
from sqlmodel import Field, SQLModel, Session, create_engine, select
from fastapi_fsp.fsp import FSPManager
from fastapi_fsp.models import PaginatedResponse
class HeroBase(SQLModel):
name: str = Field(index=True)
secret_name: str
age: Optional[int] = Field(default=None, index=True)
class Hero(HeroBase, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
class HeroPublic(HeroBase):
id: int
engine = create_engine("sqlite:///database.db", connect_args={"check_same_thread": False})
SQLModel.metadata.create_all(engine)
app = FastAPI()
def get_session():
with Session(engine) as session:
yield session
@app.get("/heroes/", response_model=PaginatedResponse[HeroPublic])
def read_heroes(*, session: Session = Depends(get_session), fsp: FSPManager = Depends(FSPManager)):
query = select(Hero)
return fsp.generate_response(query, session)
Run the app and query:
- Pagination:
GET /heroes/?page=1&per_page=10 - Sorting:
GET /heroes/?sort_by=name&order=asc - Filtering:
GET /heroes/?field=age&operator=gte&value=21
The response includes data, meta (pagination, filters, sorting), and links (self, first, next, prev, last).
Convenience methods¶
from_model()¶
Simplify common queries with from_model():
@app.get("/heroes/")
def read_heroes(session: Session = Depends(get_session), fsp: FSPManager = Depends(FSPManager)):
# Instead of:
# query = select(Hero)
# return fsp.generate_response(query, session)
# Use:
return fsp.from_model(Hero, session)
# Async version
@app.get("/heroes/")
async def read_heroes(session: AsyncSession = Depends(get_session), fsp: FSPManager = Depends(FSPManager)):
return await fsp.from_model_async(Hero, session)
Method Chaining¶
Chain configuration methods:
@app.get("/heroes/")
def read_heroes(session: Session = Depends(get_session), fsp: FSPManager = Depends(FSPManager)):
return (
fsp
.with_filters(CommonFilters.active())
.apply_config(FSPPresets.strict())
.generate_response(select(Hero), session)
)