Claude-skill-registry backend-python
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/backend-python" ~/.claude/skills/majiayu000-claude-skill-registry-backend-python && rm -rf "$T"
manifest:
skills/data/backend-python/SKILL.mdsource content
Python Backend Stack
Live docs: Add
to prompt for up-to-date FastAPI, SQLAlchemy, Pydantic documentation.use context7
Tooling (2025)
| Tool | Purpose | Why |
|---|---|---|
| uv | Package manager | 10-100x faster than pip |
| ruff | Linter + formatter | Replaces black, isort, flake8 |
| FastAPI | Web framework | Async, auto-docs, Pydantic |
| SQLAlchemy 2.0 | ORM | Async support, type hints |
| Pydantic v2 | Validation | 5-50x faster than v1 |
| pytest | Testing | See testing.md |
Project Setup
# Initialize uv init my-api cd my-api uv add fastapi sqlalchemy[asyncio] pydantic pydantic-settings uv add --dev ruff pytest pytest-asyncio httpx # pyproject.toml [tool.ruff] line-length = 100 select = ["E", "F", "I", "N", "UP", "B", "A", "C4", "SIM"] [tool.ruff.format] quote-style = "double" [tool.pytest.ini_options] asyncio_mode = "auto"
Project Structure
src/ ├── main.py # FastAPI app ├── config.py # Settings (pydantic-settings) ├── db/ │ ├── __init__.py │ ├── engine.py # Async engine + session │ └── models.py # SQLAlchemy models ├── api/ │ ├── __init__.py │ ├── deps.py # Dependencies (get_db, get_user) │ └── routes/ │ ├── __init__.py │ ├── auth.py │ └── users.py ├── schemas/ # Pydantic models │ ├── __init__.py │ └── user.py └── services/ # Business logic └── user.py tests/ ├── conftest.py └── test_users.py
FastAPI Patterns
Basic App
from fastapi import FastAPI from contextlib import asynccontextmanager @asynccontextmanager async def lifespan(app: FastAPI): # Startup await init_db() yield # Shutdown await close_db() app = FastAPI(lifespan=lifespan)
Route with Dependencies
from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession router = APIRouter(prefix="/users", tags=["users"]) @router.get("/{user_id}", response_model=UserOut) async def get_user( user_id: int, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user), ): user = await db.get(User, user_id) if not user: raise HTTPException(status_code=404, detail="User not found") return user
Pydantic Schemas
from pydantic import BaseModel, EmailStr, Field from datetime import datetime class UserCreate(BaseModel): email: EmailStr name: str = Field(min_length=1, max_length=100) class UserOut(BaseModel): id: int email: str name: str created_at: datetime model_config = {"from_attributes": True} # For ORM mode
Settings
from pydantic_settings import BaseSettings from functools import lru_cache class Settings(BaseSettings): database_url: str secret_key: str debug: bool = False model_config = {"env_file": ".env"} @lru_cache def get_settings() -> Settings: return Settings()
SQLAlchemy 2.0 Async
Engine Setup
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession from sqlalchemy.orm import sessionmaker, DeclarativeBase engine = create_async_engine( "postgresql+asyncpg://user:pass@localhost/db", echo=False, pool_size=5, max_overflow=10, ) AsyncSessionLocal = sessionmaker( engine, class_=AsyncSession, expire_on_commit=False ) class Base(DeclarativeBase): pass
Models
from sqlalchemy import String, ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship from datetime import datetime class User(Base): __tablename__ = "users" id: Mapped[int] = mapped_column(primary_key=True) email: Mapped[str] = mapped_column(String(255), unique=True, index=True) name: Mapped[str] = mapped_column(String(100)) created_at: Mapped[datetime] = mapped_column(default=datetime.utcnow) posts: Mapped[list["Post"]] = relationship(back_populates="author")
Database Dependency
from typing import AsyncGenerator async def get_db() -> AsyncGenerator[AsyncSession, None]: async with AsyncSessionLocal() as session: try: yield session await session.commit() except Exception: await session.rollback() raise
Queries
from sqlalchemy import select from sqlalchemy.orm import selectinload # Get one user = await db.get(User, user_id) # Query with filter stmt = select(User).where(User.email == email) result = await db.execute(stmt) user = result.scalar_one_or_none() # Eager load relationships stmt = select(User).options(selectinload(User.posts)).where(User.id == user_id) # Pagination stmt = select(User).offset(skip).limit(limit).order_by(User.created_at.desc()) result = await db.execute(stmt) users = result.scalars().all()
Error Handling
from fastapi import HTTPException, status from fastapi.responses import JSONResponse from fastapi.exceptions import RequestValidationError @app.exception_handler(RequestValidationError) async def validation_exception_handler(request, exc): return JSONResponse( status_code=422, content={"error": {"code": "VALIDATION_ERROR", "details": exc.errors()}}, ) # Custom exceptions class NotFoundError(Exception): def __init__(self, resource: str, id: int): self.resource = resource self.id = id @app.exception_handler(NotFoundError) async def not_found_handler(request, exc): return JSONResponse( status_code=404, content={"error": {"message": f"{exc.resource} {exc.id} not found"}}, )
Anti-patterns
| Don't | Do Instead |
|---|---|
| |
+ + | |
| SQLAlchemy 1.x style | SQLAlchemy 2.0 with |
| Pydantic v1 | Pydantic v2 (, not ) |
| Sync database calls | Async with / |
| Global DB session | Dependency injection |
| Business logic in routes | Services layer |