Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Part of a 72-plugin marketplace with 112 AI agents and 146 skills for Claude Code development automation.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/details.md
1# fastapi-templates — detailed worked examples23## Implementation Patterns45### Pattern 1: Complete FastAPI Application67```python8# main.py9from fastapi import FastAPI, Depends10from fastapi.middleware.cors import CORSMiddleware11from contextlib import asynccontextmanager1213@asynccontextmanager14async def lifespan(app: FastAPI):15"""Application lifespan events."""16# Startup17await database.connect()18yield19# Shutdown20await database.disconnect()2122app = FastAPI(23title="API Template",24version="1.0.0",25lifespan=lifespan26)2728# CORS middleware29app.add_middleware(30CORSMiddleware,31allow_origins=["*"],32allow_credentials=True,33allow_methods=["*"],34allow_headers=["*"],35)3637# Include routers38from app.api.v1.router import api_router39app.include_router(api_router, prefix="/api/v1")4041# core/config.py42from pydantic_settings import BaseSettings43from functools import lru_cache4445class Settings(BaseSettings):46"""Application settings."""47DATABASE_URL: str48SECRET_KEY: str49ACCESS_TOKEN_EXPIRE_MINUTES: int = 3050API_V1_STR: str = "/api/v1"5152class Config:53env_file = ".env"5455@lru_cache()56def get_settings() -> Settings:57return Settings()5859# core/database.py60from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession61from sqlalchemy.ext.declarative import declarative_base62from sqlalchemy.orm import sessionmaker63from app.core.config import get_settings6465settings = get_settings()6667engine = create_async_engine(68settings.DATABASE_URL,69echo=True,70future=True71)7273AsyncSessionLocal = sessionmaker(74engine,75class_=AsyncSession,76expire_on_commit=False77)7879Base = declarative_base()8081async def get_db() -> AsyncSession:82"""Dependency for database session."""83async with AsyncSessionLocal() as session:84try:85yield session86await session.commit()87except Exception:88await session.rollback()89raise90finally:91await session.close()92```9394### Pattern 2: CRUD Repository Pattern9596```python97# repositories/base_repository.py98from typing import Generic, TypeVar, Type, Optional, List99from sqlalchemy.ext.asyncio import AsyncSession100from sqlalchemy import select101from pydantic import BaseModel102103ModelType = TypeVar("ModelType")104CreateSchemaType = TypeVar("CreateSchemaType", bound=BaseModel)105UpdateSchemaType = TypeVar("UpdateSchemaType", bound=BaseModel)106107class BaseRepository(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):108"""Base repository for CRUD operations."""109110def __init__(self, model: Type[ModelType]):111self.model = model112113async def get(self, db: AsyncSession, id: int) -> Optional[ModelType]:114"""Get by ID."""115result = await db.execute(116select(self.model).where(self.model.id == id)117)118return result.scalars().first()119120async def get_multi(121self,122db: AsyncSession,123skip: int = 0,124limit: int = 100125) -> List[ModelType]:126"""Get multiple records."""127result = await db.execute(128select(self.model).offset(skip).limit(limit)129)130return result.scalars().all()131132async def create(133self,134db: AsyncSession,135obj_in: CreateSchemaType136) -> ModelType:137"""Create new record."""138db_obj = self.model(**obj_in.dict())139db.add(db_obj)140await db.flush()141await db.refresh(db_obj)142return db_obj143144async def update(145self,146db: AsyncSession,147db_obj: ModelType,148obj_in: UpdateSchemaType149) -> ModelType:150"""Update record."""151update_data = obj_in.dict(exclude_unset=True)152for field, value in update_data.items():153setattr(db_obj, field, value)154await db.flush()155await db.refresh(db_obj)156return db_obj157158async def delete(self, db: AsyncSession, id: int) -> bool:159"""Delete record."""160obj = await self.get(db, id)161if obj:162await db.delete(obj)163return True164return False165166# repositories/user_repository.py167from app.repositories.base_repository import BaseRepository168from app.models.user import User169from app.schemas.user import UserCreate, UserUpdate170171class UserRepository(BaseRepository[User, UserCreate, UserUpdate]):172"""User-specific repository."""173174async def get_by_email(self, db: AsyncSession, email: str) -> Optional[User]:175"""Get user by email."""176result = await db.execute(177select(User).where(User.email == email)178)179return result.scalars().first()180181async def is_active(self, db: AsyncSession, user_id: int) -> bool:182"""Check if user is active."""183user = await self.get(db, user_id)184return user.is_active if user else False185186user_repository = UserRepository(User)187```188189### Pattern 3: Service Layer190191```python192# services/user_service.py193from typing import Optional194from sqlalchemy.ext.asyncio import AsyncSession195from app.repositories.user_repository import user_repository196from app.schemas.user import UserCreate, UserUpdate, User197from app.core.security import get_password_hash, verify_password198199class UserService:200"""Business logic for users."""201202def __init__(self):203self.repository = user_repository204205async def create_user(206self,207db: AsyncSession,208user_in: UserCreate209) -> User:210"""Create new user with hashed password."""211# Check if email exists212existing = await self.repository.get_by_email(db, user_in.email)213if existing:214raise ValueError("Email already registered")215216# Hash password217user_in_dict = user_in.dict()218user_in_dict["hashed_password"] = get_password_hash(user_in_dict.pop("password"))219220# Create user221user = await self.repository.create(db, UserCreate(**user_in_dict))222return user223224async def authenticate(225self,226db: AsyncSession,227email: str,228password: str229) -> Optional[User]:230"""Authenticate user."""231user = await self.repository.get_by_email(db, email)232if not user:233return None234if not verify_password(password, user.hashed_password):235return None236return user237238async def update_user(239self,240db: AsyncSession,241user_id: int,242user_in: UserUpdate243) -> Optional[User]:244"""Update user."""245user = await self.repository.get(db, user_id)246if not user:247return None248249if user_in.password:250user_in_dict = user_in.dict(exclude_unset=True)251user_in_dict["hashed_password"] = get_password_hash(252user_in_dict.pop("password")253)254user_in = UserUpdate(**user_in_dict)255256return await self.repository.update(db, user, user_in)257258user_service = UserService()259```260261### Pattern 4: API Endpoints with Dependencies262263```python264# api/v1/endpoints/users.py265from fastapi import APIRouter, Depends, HTTPException, status266from sqlalchemy.ext.asyncio import AsyncSession267from typing import List268269from app.core.database import get_db270from app.schemas.user import User, UserCreate, UserUpdate271from app.services.user_service import user_service272from app.api.dependencies import get_current_user273274router = APIRouter()275276@router.post("/", response_model=User, status_code=status.HTTP_201_CREATED)277async def create_user(278user_in: UserCreate,279db: AsyncSession = Depends(get_db)280):281"""Create new user."""282try:283user = await user_service.create_user(db, user_in)284return user285except ValueError as e:286raise HTTPException(status_code=400, detail=str(e))287288@router.get("/me", response_model=User)289async def read_current_user(290current_user: User = Depends(get_current_user)291):292"""Get current user."""293return current_user294295@router.get("/{user_id}", response_model=User)296async def read_user(297user_id: int,298db: AsyncSession = Depends(get_db),299current_user: User = Depends(get_current_user)300):301"""Get user by ID."""302user = await user_service.repository.get(db, user_id)303if not user:304raise HTTPException(status_code=404, detail="User not found")305return user306307@router.patch("/{user_id}", response_model=User)308async def update_user(309user_id: int,310user_in: UserUpdate,311db: AsyncSession = Depends(get_db),312current_user: User = Depends(get_current_user)313):314"""Update user."""315if current_user.id != user_id:316raise HTTPException(status_code=403, detail="Not authorized")317318user = await user_service.update_user(db, user_id, user_in)319if not user:320raise HTTPException(status_code=404, detail="User not found")321return user322323@router.delete("/{user_id}", status_code=status.HTTP_204_NO_CONTENT)324async def delete_user(325user_id: int,326db: AsyncSession = Depends(get_db),327current_user: User = Depends(get_current_user)328):329"""Delete user."""330if current_user.id != user_id:331raise HTTPException(status_code=403, detail="Not authorized")332333deleted = await user_service.repository.delete(db, user_id)334if not deleted:335raise HTTPException(status_code=404, detail="User not found")336```337338### Pattern 5: Authentication & Authorization339340```python341# core/security.py342from datetime import datetime, timedelta343from typing import Optional344from jose import JWTError, jwt345from passlib.context import CryptContext346from app.core.config import get_settings347348settings = get_settings()349pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")350351ALGORITHM = "HS256"352353def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):354"""Create JWT access token."""355to_encode = data.copy()356if expires_delta:357expire = datetime.utcnow() + expires_delta358else:359expire = datetime.utcnow() + timedelta(minutes=15)360to_encode.update({"exp": expire})361encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=ALGORITHM)362return encoded_jwt363364def verify_password(plain_password: str, hashed_password: str) -> bool:365"""Verify password against hash."""366return pwd_context.verify(plain_password, hashed_password)367368def get_password_hash(password: str) -> str:369"""Hash password."""370return pwd_context.hash(password)371372# api/dependencies.py373from fastapi import Depends, HTTPException, status374from fastapi.security import OAuth2PasswordBearer375from jose import JWTError, jwt376from sqlalchemy.ext.asyncio import AsyncSession377378from app.core.database import get_db379from app.core.security import ALGORITHM380from app.core.config import get_settings381from app.repositories.user_repository import user_repository382383oauth2_scheme = OAuth2PasswordBearer(tokenUrl=f"{settings.API_V1_STR}/auth/login")384385async def get_current_user(386db: AsyncSession = Depends(get_db),387token: str = Depends(oauth2_scheme)388):389"""Get current authenticated user."""390credentials_exception = HTTPException(391status_code=status.HTTP_401_UNAUTHORIZED,392detail="Could not validate credentials",393headers={"WWW-Authenticate": "Bearer"},394)395396try:397payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[ALGORITHM])398user_id: int = payload.get("sub")399if user_id is None:400raise credentials_exception401except JWTError:402raise credentials_exception403404user = await user_repository.get(db, user_id)405if user is None:406raise credentials_exception407408return user409```410