FastAPI Route Patterns¶
Router Organization¶
Group routes by domain with consistent prefixes and tags:
Response Models and Status Codes¶
Always declare response_model and explicit status codes:
@router.post("/", response_model=UserResponse, status_code=201)
async def create_user(
user_in: UserCreate,
service: UserService = Depends(get_user_service),
) -> UserResponse:
return await service.create_user(user_in)
@router.get("/{user_id}", response_model=UserResponse)
async def get_user(
user_id: UUID,
service: UserService = Depends(get_user_service),
) -> UserResponse:
return await service.get_user(user_id)
@router.patch("/{user_id}", response_model=UserResponse)
async def update_user(
user_id: UUID,
user_in: UserUpdate,
service: UserService = Depends(get_user_service),
) -> UserResponse:
return await service.update_user(user_id, user_in)
@router.delete("/{user_id}", status_code=204)
async def delete_user(
user_id: UUID,
service: UserService = Depends(get_user_service),
):
await service.delete_user(user_id)
Query Parameters and Filtering¶
Use Query() for validated query parameters and Depends() for filter schemas:
from fastapi import Query
@router.get("/", response_model=Page[UserResponse])
async def list_users(
page: int = Query(1, ge=1),
size: int = Query(20, ge=1, le=100),
search: str | None = Query(None, max_length=200),
is_active: bool | None = Query(None),
service: UserService = Depends(get_user_service),
) -> Page[UserResponse]:
return await service.list_users(
page=page, size=size, search=search, is_active=is_active
)
File Uploads¶
from fastapi import UploadFile
@router.post("/{user_id}/avatar", response_model=UserResponse)
async def upload_avatar(
user_id: UUID,
file: UploadFile,
service: UserService = Depends(get_user_service),
) -> UserResponse:
if file.content_type not in ("image/jpeg", "image/png"):
raise BadRequestError("Only JPEG and PNG files are accepted")
if file.size and file.size > 5 * 1024 * 1024:
raise BadRequestError("File size must be under 5MB")
return await service.update_avatar(user_id, file)