F

Fastapi Endpoint Complete

Comprehensive skill designed for plan, build, production, ready. Includes structured workflows, validation checks, and reusable patterns for web development.

SkillClipticsweb developmentv1.0.0MIT
0 views0 copies

FastAPI Endpoint Complete

A comprehensive API development skill for building production-ready FastAPI endpoints with validation, authentication, database integration, and OpenAPI documentation.

When to Use

Choose FastAPI Endpoint Complete when:

  • Building REST API endpoints with automatic request/response validation
  • Creating APIs that need auto-generated OpenAPI/Swagger documentation
  • Developing async Python backends with high performance requirements
  • Implementing CRUD operations with SQLAlchemy or other ORMs

Consider alternatives when:

  • Building a Django application — use Django REST Framework
  • Creating a simple script API — use Flask for minimal setup
  • Working with GraphQL — use Strawberry or Ariadne

Quick Start

# Install FastAPI with all dependencies pip install "fastapi[standard]" sqlalchemy alembic python-jose passlib[bcrypt] # Run the development server uvicorn main:app --reload --port 8000
from fastapi import FastAPI, HTTPException, Depends, Query, Path, status from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel, Field, EmailStr from typing import Optional from datetime import datetime app = FastAPI( title="My API", version="1.0.0", description="Production-ready API with FastAPI" ) app.add_middleware( CORSMiddleware, allow_origins=["http://localhost:3000"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Pydantic models for validation class UserCreate(BaseModel): email: EmailStr name: str = Field(min_length=2, max_length=100) password: str = Field(min_length=8) class UserResponse(BaseModel): id: int email: str name: str created_at: datetime class Config: from_attributes = True class UserUpdate(BaseModel): name: Optional[str] = Field(None, min_length=2, max_length=100) email: Optional[EmailStr] = None # CRUD endpoints @app.post("/users", response_model=UserResponse, status_code=status.HTTP_201_CREATED) async def create_user(user: UserCreate, db=Depends(get_db)): existing = await db.execute( select(User).where(User.email == user.email) ) if existing.scalar_one_or_none(): raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail="Email already registered" ) db_user = User(**user.model_dump()) db.add(db_user) await db.commit() await db.refresh(db_user) return db_user @app.get("/users", response_model=list[UserResponse]) async def list_users( skip: int = Query(0, ge=0), limit: int = Query(20, ge=1, le=100), search: Optional[str] = Query(None, min_length=1), db=Depends(get_db) ): query = select(User) if search: query = query.where(User.name.ilike(f"%{search}%")) query = query.offset(skip).limit(limit) result = await db.execute(query) return result.scalars().all() @app.get("/users/{user_id}", response_model=UserResponse) async def get_user( user_id: int = Path(gt=0), db=Depends(get_db) ): user = await db.get(User, user_id) if not user: raise HTTPException(status_code=404, detail="User not found") return user @app.patch("/users/{user_id}", response_model=UserResponse) async def update_user( user_id: int, updates: UserUpdate, db=Depends(get_db) ): user = await db.get(User, user_id) if not user: raise HTTPException(status_code=404, detail="User not found") update_data = updates.model_dump(exclude_unset=True) for field, value in update_data.items(): setattr(user, field, value) await db.commit() await db.refresh(user) return user @app.delete("/users/{user_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_user(user_id: int, db=Depends(get_db)): user = await db.get(User, user_id) if not user: raise HTTPException(status_code=404, detail="User not found") await db.delete(user) await db.commit()

Core Concepts

FastAPI Architecture Patterns

PatternUse CaseComponents
Router-basedFeature separationAPIRouter per resource
Dependency InjectionShared logic (auth, db)Depends()
MiddlewareCross-cutting concernsCORS, logging, timing
Background TasksAsync work after responseBackgroundTasks
EventsStartup/shutdown logiclifespan context manager
Exception HandlersCustom error responses@app.exception_handler

Authentication with JWT

from fastapi import Depends, HTTPException, status from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials from jose import JWTError, jwt from datetime import datetime, timedelta security = HTTPBearer() SECRET_KEY = "your-secret-key" ALGORITHM = "HS256" def create_access_token(data: dict, expires_delta: timedelta = timedelta(hours=1)): to_encode = data.copy() expire = datetime.utcnow() + expires_delta to_encode.update({"exp": expire}) return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) async def get_current_user( credentials: HTTPAuthorizationCredentials = Depends(security), db=Depends(get_db) ): try: payload = jwt.decode(credentials.credentials, SECRET_KEY, algorithms=[ALGORITHM]) user_id = payload.get("sub") if not user_id: raise HTTPException(status_code=401, detail="Invalid token") except JWTError: raise HTTPException(status_code=401, detail="Invalid token") user = await db.get(User, int(user_id)) if not user: raise HTTPException(status_code=401, detail="User not found") return user # Protected endpoint @app.get("/me", response_model=UserResponse) async def get_current_user_profile(user=Depends(get_current_user)): return user

Configuration

OptionDescriptionDefault
hostServer bind address"0.0.0.0"
portServer port8000
reloadAuto-reload on code changestrue (dev)
workersNumber of Uvicorn workers1
cors_originsAllowed CORS origins["*"] (dev)
docs_urlSwagger UI path"/docs"
redoc_urlReDoc documentation path"/redoc"
log_levelLogging level"info"

Best Practices

  1. Use Pydantic models for all request and response schemas to get automatic validation, serialization, and OpenAPI documentation — never manually parse request bodies or validate fields in endpoint logic
  2. Organize endpoints into routers by resource (users_router, orders_router) and include them in the main app with prefixes to keep the codebase maintainable as the API grows
  3. Use dependency injection for cross-cutting concerns like database sessions, authentication, and rate limiting so endpoint functions stay focused on business logic
  4. Return appropriate HTTP status codes — 201 for creation, 204 for deletion, 409 for conflicts, 422 for validation errors — clients depend on status codes for error handling
  5. Add pagination to all list endpoints from the start with skip and limit parameters and sensible defaults; retrofitting pagination into endpoints that return unbounded results causes breaking changes

Common Issues

Circular import errors with routers: Splitting FastAPI apps into multiple files often creates circular imports when models and dependencies reference each other. Use a separate deps.py file for shared dependencies, and import types using TYPE_CHECKING guards to break circular references.

Async database sessions leaking: Forgetting to close database sessions in error paths causes connection pool exhaustion. Use FastAPI's dependency injection with yield to ensure sessions are always closed: async def get_db(): async with session() as s: yield s.

OpenAPI schema conflicts with optional fields: Using Optional[str] in Pydantic models generates different OpenAPI schemas than str | None, and inconsistent usage confuses API clients. Standardize on one approach across all models and verify the generated OpenAPI spec matches your documentation expectations.

Community

Reviews

Write a review

No reviews yet. Be the first to review this template!

Similar Templates