Python’s third-party ecosystem โ packages available on PyPI and installed with pip โ is one of its greatest strengths. For FastAPI web development, a small set of well-maintained packages handles nearly every concern: validation, database access, migrations, authentication, email, file storage, and testing. Knowing which package to reach for โ and crucially, which packages are standard choices in the FastAPI community vs alternatives โ lets you build on proven foundations rather than reinventing wheels. This lesson surveys the core packages you will use throughout the rest of this series.
The Core FastAPI Ecosystem
| Package | Purpose | Install |
|---|---|---|
| fastapi | The web framework โ routing, validation, docs | pip install fastapi |
| uvicorn | ASGI server โ runs the FastAPI app | pip install uvicorn[standard] |
| pydantic | Data validation, settings management (comes with FastAPI) | pip install pydantic |
| pydantic-settings | Environment variable / .env file settings | pip install pydantic-settings |
| sqlalchemy | ORM + query builder for PostgreSQL | pip install sqlalchemy |
| alembic | Database schema migrations | pip install alembic |
| psycopg2-binary | PostgreSQL driver for Python | pip install psycopg2-binary |
| asyncpg | Async PostgreSQL driver (faster) | pip install asyncpg |
| python-jose | JWT creation and verification | pip install "python-jose[cryptography]" |
| passlib | Password hashing (bcrypt) | pip install "passlib[bcrypt]" |
| python-multipart | File upload support for FastAPI | pip install python-multipart |
| httpx | Async HTTP client + test client | pip install httpx |
| python-dotenv | Load .env files into environment | pip install python-dotenv |
from pydantic import validator in older tutorials, that is v1 syntax โ the v2 equivalent is @field_validator. Always check which Pydantic version a tutorial or Stack Overflow answer targets before copying code.pip install "fastapi[all]" installs FastAPI along with Uvicorn, email-validator, and other optional extras that FastAPI can use. For production, be more selective โ only install what you actually use. Unnecessary packages increase image size in Docker deployments and create more surface area for security vulnerabilities.pip show packagename to see the installed version and check the package’s migration guide for any breaking changes.pydantic-settings โ Configuration Management
from pydantic_settings import BaseSettings
from pydantic import AnyHttpUrl
from typing import List
class Settings(BaseSettings):
# Database
database_url: str = "postgresql://localhost/blogdb"
# Auth
secret_key: str = "changeme-in-production"
algorithm: str = "HS256"
access_token_expire_minutes: int = 30
# CORS
allowed_origins: List[AnyHttpUrl] = ["http://localhost:5173"]
# App
app_name: str = "Blog API"
debug: bool = False
class Config:
env_file = ".env" # load from .env file
case_sensitive = False # DATABASE_URL or database_url both work
# Singleton โ create once, import everywhere
settings = Settings()
# Usage anywhere:
# from app.config import settings
# print(settings.database_url)
Quick Overview of Key Packages
# โโ passlib โ password hashing โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def hash_password(plain: str) -> str:
return pwd_context.hash(plain)
def verify_password(plain: str, hashed: str) -> bool:
return pwd_context.verify(plain, hashed)
# โโ python-jose โ JWT tokens โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
from jose import jwt, JWTError
from datetime import datetime, timedelta, timezone
SECRET_KEY = "your-256-bit-secret"
ALGORITHM = "HS256"
def create_access_token(data: dict, expires_minutes: int = 30) -> str:
payload = {
**data,
"exp": datetime.now(timezone.utc) + timedelta(minutes=expires_minutes)
}
return jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
def decode_token(token: str) -> dict:
return jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
# โโ httpx โ async HTTP client โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
import httpx
async def fetch_external_api(url: str) -> dict:
async with httpx.AsyncClient() as client:
response = await client.get(url, timeout=10.0)
response.raise_for_status() # raises on 4xx/5xx
return response.json()
# httpx also provides a sync test client for FastAPI tests:
# from httpx import TestClient (used in pytest fixtures)
Development Tools
| Tool | Purpose | Command |
|---|---|---|
| pytest | Test runner | pip install pytest pytest-asyncio |
| black | Code formatter (auto-format) | pip install black |
| ruff | Fast linter (replaces flake8, isort) | pip install ruff |
| mypy | Static type checker | pip install mypy |
| pre-commit | Run tools before every commit | pip install pre-commit |
# Format code with black
black app/ tests/
# Lint with ruff (fast)
ruff check app/
ruff check --fix app/ # auto-fix fixable issues
# Type check with mypy
mypy app/
# Run tests with pytest
pytest tests/ -v
pytest tests/ -v --cov=app # with coverage report
Common Mistakes
Mistake 1 โ Using Pydantic v1 syntax with v2 installed
โ Wrong โ v1 validator syntax in v2:
from pydantic import validator # ImportError in Pydantic v2!
โ Correct โ v2 syntax:
from pydantic import field_validator # โ Pydantic v2
Mistake 2 โ Using SQLAlchemy 1.x query syntax with 2.0 installed
โ Wrong โ legacy query API (deprecated in 2.0):
db.query(Post).filter(Post.id == 1).first() # legacy โ still works but deprecated
โ Correct โ SQLAlchemy 2.0 style:
from sqlalchemy import select
db.execute(select(Post).where(Post.id == 1)).scalar_one_or_none() # โ 2.0
Mistake 3 โ Hardcoding secrets in code instead of using pydantic-settings
โ Wrong โ secret in source code:
SECRET_KEY = "super-secret-do-not-commit" # committed to git!
โ Correct โ read from environment:
class Settings(BaseSettings):
secret_key: str # required โ must be in .env or environment โ
Quick Reference โ Install Command
# Install the complete FastAPI + PostgreSQL stack
pip install fastapi uvicorn[standard] sqlalchemy alembic \
psycopg2-binary pydantic-settings \
"python-jose[cryptography]" "passlib[bcrypt]" \
python-multipart httpx python-dotenv
# Install dev tools
pip install pytest pytest-asyncio black ruff mypy