Sync Quickstart (SQLAlchemy)¶
This guide walks through a complete CRUD API using BaseViewset with synchronous SQLAlchemy.
Full example¶
Save as main.py in an empty folder and run python main.py or uvicorn main:app --reload:
from fastapi import FastAPI
from pydantic import BaseModel, ConfigDict
from sqlalchemy import Column, Integer, String
from typing import Optional
from fastapi_viewsets import BaseViewset
from fastapi_viewsets.db_conf import Base, engine, get_session
app = FastAPI()
class Item(Base):
"""Example SQLAlchemy model."""
__tablename__ = "items"
id = Column(Integer, primary_key=True)
name = Column(String(255), nullable=False)
class ItemSchema(BaseModel):
"""Pydantic model for request and response bodies."""
model_config = ConfigDict(from_attributes=True)
id: Optional[int] = None
name: str
Base.metadata.create_all(bind=engine)
items = BaseViewset(
endpoint="/items",
model=Item,
response_model=ItemSchema,
db_session=get_session,
tags=["items"],
)
items.register(methods=["LIST", "GET", "POST", "PATCH", "DELETE"])
app.include_router(items)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)
What just happened¶
-
Model —
Itemis a standard SQLAlchemy declarative model. It inherits fromBase, which is the lazy SQLAlchemy declarative base provided byfastapi_viewsets.db_conf. -
Schema —
ItemSchemais a Pydantic v2 model withmodel_config = ConfigDict(from_attributes=True). This enablesmodel_validate()to read directly from ORM objects (replacing the old v1class Config: orm_mode = True). -
Viewset —
BaseViewsetis instantiated with:endpoint— the base URL path ("/items")model— the SQLAlchemy model classresponse_model— the Pydantic schema (used for both request bodies and responses)db_session— a session factory (here,get_sessionfromdb_conf)tags— OpenAPI tag grouping
-
Register —
register()wires the CRUD routes. Pass a list of logical methods:Method HTTP Path Description LISTGET/itemsList with limit/offsetGETGET/items/{id}Retrieve single item POSTPOST/itemsCreate item PUTPUT/items/{id}Full update PATCHPATCH/items/{id}Partial update (only set fields) DELETEDELETE/items/{id}Delete item -
Router —
app.include_router(items)mounts the viewset (which subclassesAPIRouter) on the FastAPI app.
Testing the endpoints¶
Start the server:
Create an item:
curl -X POST http://127.0.0.1:8000/items \
-H "Content-Type: application/json" \
-d '{"name": "apple"}'
# {"id":1,"name":"apple"}
List items:
curl http://127.0.0.1:8000/items
# [{"id":1,"name":"apple"}]
curl "http://127.0.0.1:8000/items?limit=10&offset=0"
Get a single item:
Patch an item:
curl -X PATCH http://127.0.0.1:8000/items/1 \
-H "Content-Type: application/json" \
-d '{"name": "banana"}'
# {"id":1,"name":"banana"}
Delete an item:
Interactive API docs are available at http://127.0.0.1:8000/docs.
Environment configuration¶
By default, db_conf falls back to sqlite:///<cwd>/base.db. To use a real database, create a .env file:
See ORM Adapters for all supported databases and drivers.
Next steps¶
- Async Quickstart — async version with
AsyncBaseViewset - Overriding Handlers — custom search, ordering, and error handling
- Authentication — protecting endpoints with OAuth2