Tags: python, fastapi, pydantic, starlette, async, rest, api, backend
Level: intermediate
TL;DR: High-performance Python web framework built on Starlette and Pydantic with native async support, automatic OpenAPI/Swagger docs, and dependency injection.
Built on ASGI standard via Starlette for high concurrency and async execution.
Request parsing and response validation handled via Pydantic type annotations.
Interactive documentation generated automatically via Swagger UI (/docs) and ReDoc (/redoc).
Native Dependency Injection system using Depends() for DB sessions, security, and shared logic.
Background tasks executed out-of-the-box via BackgroundTasks without external brokers for simple jobs.
Automatic serialisation to JSON compliant with JSON Schema and OpenAPI 3.0+.
Native support for WebSocket connections, OAuth2 with JWT tokens, and CORS middleware.
Seamless compatibility with both synchronous (def) and asynchronous (async def) route handlers.
Q: When should you define route handlers with async def versus standard def?R: I use async def when performing non-blocking I/O operations with async-compatible libraries (like HTTPX or asyncpg). For standard blocking calls (like synchronous database drivers), I declare regular def so FastAPI automatically offloads them to an external threadpool, preventing the event loop from blocking.
Q: How does Dependency Injection work in FastAPI, and what is its main advantage?R: FastAPI uses Depends() to declare dependencies directly in route signatures. It resolves hierarchies recursively, handles cleanup with yield context managers, and allows effortless mocking during unit tests via app.dependency_overrides.
Q: What is the difference between Pydantic validation errors and HTTP exceptions?R: Pydantic raises RequestValidationError (422 Unprocessable Entity) automatically when request data fails schema types. For custom business logic failures, I explicitly raise HTTPException with a specific status code and detail payload.
Writing blocking synchronous calls inside async def routes, which freezes the single-threaded event loop.
Using mutable default values in route function signatures instead of Field(...) or Depends().
Forgetting that yield dependencies execute teardown code after the response is sent; catching unexpected exceptions there won't change the HTTP status.
Confusing Pydantic BaseModel attributes with ORM entity attributes when from_attributes = True (formerly orm_mode) is omitted.
Not defining response models (response_model), which leaks sensitive internal model attributes (like hashed passwords) to clients.
# Install FastAPI with standard dependencies (Uvicorn, Pydantic, etc.)
pip install "fastapi[standard]"
# Run development server with auto-reload
uvicorn main:app --reload --port 8000
Python
```from fastapi import FastAPI, Depends, HTTPException, status
from pydantic import BaseModel, EmailStr
from typing import Annotated
app = FastAPI()
class UserIn(BaseModel):
username: str
email: EmailStr
class UserOut(BaseModel):
id: int
username: str
email: EmailStr
class Config:
from_attributes = True
async def get_db_session():
db = {"connected": True}
try:
yield db
finally:
db["connected"] = False
@app.post("/users/", response_model=UserOut, status_code=status.HTTP_201_CREATED)
async def create_user(
user: UserIn,
db: Annotated[dict, Depends(get_db_session)]
):
if not db["connected"]:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Database unavailable"
)
return {"id": 1, "username": user.username, "email": user.email}
```
[ ] Understand threadpool dispatch mechanics for regular def routes
[ ] Master OAuth2 with Password (and hashing), Bearer with JWT tokens
[ ] Review yield lifecycle in app.dependency_overrides for integration testing with httpx.AsyncClient
[ ] Master Pydantic v2 migration changes (field_validator, model_validator, from_attributes)
[ ] Review global exception handlers using @app.exception_handler
Official FastAPI Documentation (fastapi.tiangolo.com)
Starlette Toolkit Documentation (encode.io/starlette)
Pydantic Documentation (docs.pydantic.dev)