Agent skill
fastapi-generator
Generates FastAPI endpoints with proper Pydantic models, dependency injection, async handlers, and OpenAPI documentation. Use when building Python REST APIs.
Install this agent skill to your Project
npx add-skill https://github.com/Dexploarer/claudius-skills/tree/main/examples/intermediate/framework-skills/fastapi-generator
SKILL.md
FastAPI Endpoint Generator Skill
Expert at creating modern FastAPI applications with async/await, Pydantic models, and proper architecture.
When to Activate
- "create FastAPI endpoint for [resource]"
- "generate Python API with FastAPI"
- "build FastAPI routes for [feature]"
- "scaffold FastAPI application"
Complete FastAPI Structure
1. Main Router
# app/routers/users.py
from fastapi import APIRouter, Depends, HTTPException, Query, status
from typing import List, Optional
from ..schemas.user import UserCreate, UserUpdate, UserResponse, UserListResponse
from ..services.user_service import UserService
from ..dependencies import get_current_user, get_user_service
router = APIRouter(prefix="/users", tags=["users"])
@router.get("/", response_model=UserListResponse)
async def get_users(
skip: int = Query(0, ge=0),
limit: int = Query(10, ge=1, le=100),
search: Optional[str] = None,
service: UserService = Depends(get_user_service),
):
"""
Retrieve list of users with pagination.
- **skip**: Number of records to skip
- **limit**: Maximum number of records to return
- **search**: Optional search query
"""
users, total = await service.get_all(skip=skip, limit=limit, search=search)
return UserListResponse(
users=users,
total=total,
page=skip // limit + 1,
page_size=limit,
)
@router.get("/{user_id}", response_model=UserResponse)
async def get_user(
user_id: int,
service: UserService = Depends(get_user_service),
):
"""Get user by ID"""
user = await service.get_by_id(user_id)
if not user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found"
)
return user
@router.post("/", response_model=UserResponse, status_code=status.HTTP_201_CREATED)
async def create_user(
user_data: UserCreate,
service: UserService = Depends(get_user_service),
):
"""Create a new user"""
return await service.create(user_data)
@router.put("/{user_id}", response_model=UserResponse)
async def update_user(
user_id: int,
user_data: UserUpdate,
service: UserService = Depends(get_user_service),
current_user = Depends(get_current_user),
):
"""Update existing user"""
if current_user.id != user_id and current_user.role != "admin":
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Not authorized to update this user"
)
user = await service.update(user_id, user_data)
if not user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found"
)
return user
@router.delete("/{user_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_user(
user_id: int,
service: UserService = Depends(get_user_service),
current_user = Depends(get_current_user),
):
"""Delete a user"""
if current_user.role != "admin":
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Admin access required"
)
success = await service.delete(user_id)
if not success:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found"
)
2. Pydantic Schemas
# app/schemas/user.py
from pydantic import BaseModel, EmailStr, Field, validator
from typing import Optional, List
from datetime import datetime
from enum import Enum
class UserRole(str, Enum):
USER = "user"
ADMIN = "admin"
MODERATOR = "moderator"
class UserBase(BaseModel):
email: EmailStr
name: str = Field(..., min_length=2, max_length=100)
role: UserRole = UserRole.USER
class UserCreate(UserBase):
password: str = Field(..., min_length=8)
@validator('password')
def validate_password(cls, v):
if not any(c.isupper() for c in v):
raise ValueError('Password must contain uppercase letter')
if not any(c.isdigit() for c in v):
raise ValueError('Password must contain a digit')
return v
class UserUpdate(BaseModel):
email: Optional[EmailStr] = None
name: Optional[str] = Field(None, min_length=2, max_length=100)
password: Optional[str] = Field(None, min_length=8)
role: Optional[UserRole] = None
class UserResponse(UserBase):
id: int
created_at: datetime
updated_at: datetime
class Config:
from_attributes = True
class UserListResponse(BaseModel):
users: List[UserResponse]
total: int
page: int
page_size: int
3. Service Layer
# app/services/user_service.py
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func, or_
from typing import Optional, Tuple, List
from ..models.user import User
from ..schemas.user import UserCreate, UserUpdate
from ..core.security import get_password_hash
from fastapi import HTTPException, status
class UserService:
def __init__(self, db: AsyncSession):
self.db = db
async def get_all(
self,
skip: int = 0,
limit: int = 10,
search: Optional[str] = None
) -> Tuple[List[User], int]:
"""Get all users with pagination and search"""
query = select(User)
if search:
query = query.where(
or_(
User.name.ilike(f"%{search}%"),
User.email.ilike(f"%{search}%")
)
)
# Get total count
count_query = select(func.count()).select_from(query.subquery())
total_result = await self.db.execute(count_query)
total = total_result.scalar()
# Get paginated results
query = query.offset(skip).limit(limit)
result = await self.db.execute(query)
users = result.scalars().all()
return users, total
async def get_by_id(self, user_id: int) -> Optional[User]:
"""Get user by ID"""
result = await self.db.execute(
select(User).where(User.id == user_id)
)
return result.scalar_one_or_none()
async def get_by_email(self, email: str) -> Optional[User]:
"""Get user by email"""
result = await self.db.execute(
select(User).where(User.email == email)
)
return result.scalar_one_or_none()
async def create(self, user_data: UserCreate) -> User:
"""Create new user"""
# Check if email exists
existing_user = await self.get_by_email(user_data.email)
if existing_user:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail="Email already registered"
)
# Create user
hashed_password = get_password_hash(user_data.password)
db_user = User(
**user_data.dict(exclude={'password'}),
hashed_password=hashed_password
)
self.db.add(db_user)
await self.db.commit()
await self.db.refresh(db_user)
return db_user
async def update(self, user_id: int, user_data: UserUpdate) -> Optional[User]:
"""Update user"""
user = await self.get_by_id(user_id)
if not user:
return None
update_data = user_data.dict(exclude_unset=True)
if 'password' in update_data:
update_data['hashed_password'] = get_password_hash(update_data.pop('password'))
for field, value in update_data.items():
setattr(user, field, value)
await self.db.commit()
await self.db.refresh(user)
return user
async def delete(self, user_id: int) -> bool:
"""Delete user"""
user = await self.get_by_id(user_id)
if not user:
return False
await self.db.delete(user)
await self.db.commit()
return True
4. Dependencies
# app/dependencies.py
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from sqlalchemy.ext.asyncio import AsyncSession
from .database import get_db
from .services.user_service import UserService
from .core.security import decode_token
security = HTTPBearer()
async def get_user_service(db: AsyncSession = Depends(get_db)) -> UserService:
"""Dependency for user service"""
return UserService(db)
async def get_current_user(
credentials: HTTPAuthorizationCredentials = Depends(security),
db: AsyncSession = Depends(get_db)
):
"""Get current authenticated user"""
token = credentials.credentials
payload = decode_token(token)
if not payload:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid or expired token"
)
user_service = UserService(db)
user = await user_service.get_by_id(payload.get("sub"))
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="User not found"
)
return user
File Structure
app/
├── main.py # FastAPI app initialization
├── routers/
│ ├── __init__.py
│ └── users.py
├── schemas/
│ ├── __init__.py
│ └── user.py
├── services/
│ ├── __init__.py
│ └── user_service.py
├── models/
│ ├── __init__.py
│ └── user.py
├── core/
│ ├── __init__.py
│ ├── config.py
│ └── security.py
├── dependencies.py
└── database.py
Best Practices
- ✅ Use async/await for all I/O operations
- ✅ Pydantic models for validation
- ✅ Dependency injection
- ✅ Proper HTTP status codes
- ✅ OpenAPI documentation
- ✅ Type hints everywhere
- ✅ Service layer for business logic
- ✅ Proper error handling
- ✅ Security (password hashing, JWT)
- ✅ Pagination for lists
- ✅ Database connection pooling
- ✅ CORS configuration
Output Checklist
- ✅ Router with endpoints
- ✅ Pydantic schemas
- ✅ Service layer
- ✅ Dependencies setup
- ✅ Error handling
- ✅ Authentication
- ✅ Tests
- 📝 OpenAPI docs auto-generated
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
smart-contract-generator
Generates Solidity smart contracts with security best practices (ERC-20, ERC-721, ERC-1155, custom). Use when user asks to "create smart contract", "solidity contract", "erc20 token", "nft contract", or "web3 contract".
threejs-scene-builder
Comprehensive Three.js and React Three Fiber skill for creating 3D scenes, characters, NPCs, procedural generation, animation retargeting, and interactive experiences. Use when user asks to "create Three.js scene", "setup React Three Fiber", "add 3D character", "create NPC AI", "procedural 3D generation", "retarget animation", "setup avatar system", or "create 3D game".
wcag-compliance-checker
Checks websites for WCAG 2.1 Level AA compliance, identifies accessibility violations, and provides remediation guidance. Use when user asks to "check accessibility", "wcag compliance", "a11y audit", "accessibility violations", or "screen reader testing".
kubernetes-manifest-generator
Generates Kubernetes manifests (Deployments, Services, Ingress, ConfigMaps, Secrets) with best practices for production workloads. Use when user asks to "create k8s manifest", "generate Kubernetes deployment", "setup k8s service", or "create Kubernetes resources".
terraform-module-builder
Generates reusable Terraform modules with best practices for AWS, Azure, GCP infrastructure as code. Use when user asks to "create Terraform module", "generate IaC module", "setup Terraform", or "create infrastructure module".
translation-key-extractor
Extracts hardcoded strings from code and converts them to translation keys for i18n. Use when user asks to "extract translations", "find hardcoded strings", "internationalize code", "setup i18n", or "create translation files".
Didn't find tool you were looking for?