Python FastAPI Backend with Best Practices
A comprehensive skill for building modern Python backend applications using FastAPI and industry-standard tooling.
Overview
This skill guides you in developing Python 3.12 applications with FastAPI framework, incorporating authentication, database management, caching, rate limiting, and email functionality while following Python best practices and PEP 8 standards.
Tech Stack
**Python Version**: 3.12**Core Frameworks**: - `pydantic` - Data validation and settings management
- `fastapi` - Modern async web framework
- `sqlalchemy` - Database ORM
**Dependency Management**: `poetry`**Database Migrations**: `alembic`**Additional Libraries**: - `fastapi-users` - User management
- `fastapi-jwt-auth` - JWT authentication
- `fastapi-mail` - Email sending
- `fastapi-cache` - Response caching
- `fastapi-limiter` - API rate limiting
- `fastapi-pagination` - Result pagination
Instructions
1. Project Setup
Use Python 3.12 as the runtime versionInitialize projects with `poetry init` for dependency managementSet up `alembic` for database migrations with proper migration scriptsUse virtual environments (`venv` or poetry's built-in env) to isolate dependencies2. Code Style and Structure
**Follow PEP 8 Standards**:
Use 4 spaces for indentationLimit lines to 79 characters for code, 72 for commentsUse snake_case for functions and variablesUse PascalCase for class namesSeparate top-level functions and classes with two blank lines**Naming Conventions**:
Choose descriptive, meaningful names for variables, functions, and classesAvoid single-letter names except for loop countersUse verb phrases for functions (e.g., `get_user`, `validate_email`)Use noun phrases for classes and variables3. Documentation
**Docstrings**:
Add docstrings to all public modules, functions, classes, and methodsUse triple quotes for docstringsInclude description, parameters, return values, and exceptionsExample format: ```python
def create_user(email: str, password: str) -> User:
"""
Create a new user account.
Args:
email: User's email address
password: Plain text password to be hashed
Returns:
User: The created user object
Raises:
ValueError: If email is invalid or already exists
"""
```
4. Type Hints
Use type hints for all function parameters and return valuesLeverage Pydantic models for request/response validationUse `typing` module for complex types (List, Dict, Optional, Union)Example: ```python
from typing import List, Optional
from pydantic import BaseModel
def get_users(limit: int = 10) -> List[User]:
pass
```
5. Code Simplicity
Keep functions small and focused on a single responsibilityAvoid deep nesting; use early returnsPrefer list comprehensions over traditional loops when they improve readabilityExample: ```python
# Good
active_users = [user for user in users if user.is_active]
# Avoid when not needed
active_users = []
for user in users:
if user.is_active:
active_users.append(user)
```
6. Exception Handling
Use try-except blocks to handle exceptions gracefullyCatch specific exceptions, not bare `except:`Use FastAPI's `HTTPException` for API errorsLog exceptions for debuggingExample: ```python
from fastapi import HTTPException
try:
user = await user_service.get_user(user_id)
except UserNotFoundError:
raise HTTPException(status_code=404, detail="User not found")
except DatabaseError as e:
logger.error(f"Database error: {e}")
raise HTTPException(status_code=500, detail="Internal server error")
```
7. FastAPI Integration
**User Management**:
Use `fastapi-users` for registration, login, and user management endpointsImplement proper password hashing and validation**Authentication**:
Use `fastapi-jwt-auth` for JWT token generation and validationImplement refresh token mechanismProtect routes with authentication dependencies**Caching**:
Use `fastapi-cache` for expensive operationsCache database queries, external API calls, and computed resultsSet appropriate TTL values**Rate Limiting**:
Use `fastapi-limiter` to prevent API abuseApply different limits for authenticated vs. anonymous usersConfigure per-endpoint rate limits**Pagination**:
Use `fastapi-pagination` for list endpointsSupport both offset and cursor-based paginationReturn total count in paginated responses**Email**:
Use `fastapi-mail` for transactional emailsImplement async email sending to avoid blockingUse templates for email content8. Database Management
**SQLAlchemy**:
Define models with proper relationshipsUse async SQLAlchemy for non-blocking database operationsImplement repository pattern for data access**Alembic Migrations**:
Generate migrations after model changes: `alembic revision --autogenerate`Review auto-generated migrations before applyingUse meaningful migration messagesTest migrations in development before production9. Testing
Write unit tests for business logic using `pytest`Use `pytest-asyncio` for async testsImplement integration tests for API endpointsUse test fixtures for database setup and teardownAim for high test coverage (>80%)Mock external dependencies10. Global Variables
Avoid global variables; use dependency injection insteadUse FastAPI's dependency system for shared resourcesStore configuration in Pydantic `BaseSettings` classesExample: ```python
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
database_url: str
secret_key: str
class Config:
env_file = ".env"
```
Example Project Structure
```
project/
├── alembic/ # Database migrations
├── app/
│ ├── api/ # API routes
│ ├── core/ # Configuration, security
│ ├── models/ # SQLAlchemy models
│ ├── schemas/ # Pydantic schemas
│ ├── services/ # Business logic
│ └── main.py # FastAPI app instance
├── tests/ # Test suite
├── pyproject.toml # Poetry dependencies
└── .env # Environment variables
```
Important Notes
Always use virtual environments to avoid dependency conflictsKeep dependencies up to date but test before upgrading in productionUse environment variables for sensitive configurationNever commit secrets or API keys to version controlImplement proper logging for debugging and monitoringFollow the principle of least privilege for database usersUse async/await for I/O-bound operations to maximize performance