Python Backend Expert
alembic database migrations
When reviewing or writing code, apply these guidelines:
- Use alembic for database migrations.
django class based views for htmx
When reviewing or writing code, apply these guidelines:
- Use Django's class-based views for HTMX responses
django form handling
When reviewing or writing code, apply these guidelines:
- Implement Django forms for form handling
- Use Django's form validation for HTMX requests
django forms
When reviewing or writing code, apply these guidelines:
- Utilize Django's form and model form classes for form handling and validation.
- Use Django's validation framework to validate form and model data.
- Keep business logic in models and forms; keep views light and focused on request handling.
django framework rules
When reviewing or writing code, apply these guidelines:
- You always use the latest stable version of Django, and you are familiar with the latest features and best practices.
django middleware
When reviewing or writing code, apply these guidelines:
- Use middleware judiciously to handle cross-cutting concerns like authentication, logging, and caching.
- Use Django’s middleware for common tasks such as authentication, logging, and security.
django middleware for request response
When reviewing or writing code, apply these guidelines:
- Utilize Django's middleware for request/response processing
django models
When reviewing or writing code, apply these guidelines:
- Leverage Django’s ORM for database interactions; avoid raw SQL queries unless necessary for performance.
- Keep business logic in models and forms; keep views light and focused on request handling.
django orm for database operations
When reviewing or writing code, apply these guidelines:
- Implement Django ORM for database operations
django rest framework
When reviewing or writing code, apply these guidelines:
- Use Django templates for rendering HTML and DRF serializers for JSON responses
django 5.x features (2025+)
When reviewing or writing code, apply these guidelines:
- Django 5.2 is the current LTS (Long-Term Support) release; target it for new projects (supported until 2028)
- Use database-computed default values via
db_default on model fields (e.g., db_default=Now()) instead of Python-side defaults where the database should own the value
- Use facet filters in the Django admin (
ModelAdmin.show_facets) to get counts alongside filter options
- Leverage improved async ORM support: Django 5.x expands
async-native queryset methods — prefer await qs.acount(), await qs.afirst(), async for obj in qs in async views
- Use declarative middleware configuration with
MIDDLEWARE list; async-capable middleware is preferred for high-throughput ASGI deployments
- Use
LoginRequiredMiddleware (Django 5.1+) instead of decorating every view when all views require authentication
- Use
GeneratedField for database-generated columns (computed from other columns at the DB level)
fastapi patterns (2025+)
When reviewing or writing code, apply these guidelines:
Use the lifespan context manager (not deprecated @app.on_event) for startup/shutdown resource management:
from contextlib import asynccontextmanager
from fastapi import FastAPI
@asynccontextmanager
async def lifespan(app: FastAPI):
# startup: initialize DB pool, HTTP clients, caches
app.state.db_pool = await create_pool()
yield
# shutdown: close resources
await app.state.db_pool.close()
app = FastAPI(lifespan=lifespan)
Use Pydantic v2 models for all request/response schemas; Pydantic v2 is the default in FastAPI 0.100+. Use model_config = ConfigDict(...) instead of the inner class Config
Use pydantic-settings (BaseSettings) with lru_cache for config management:
from functools import lru_cache
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
database_url: str
model_config = ConfigDict(env_prefix="APP_")
@lru_cache
def get_settings() -> Settings:
return Settings()
Scope dependencies correctly: per-request (DB sessions, auth), router-level (audit logging, namespace caches), application lifespan (Kafka producers, feature flag SDKs, tracing exporters)
Use Annotated type hints with Depends for cleaner dependency signatures:
from typing import Annotated
from fastapi import Depends
DbSession = Annotated[AsyncSession, Depends(get_db)]
CurrentUser = Annotated[User, Depends(get_current_user)]
Structure projects by domain: routers/, services/, repositories/, schemas/, models/ — avoid flat single-file apps beyond prototypes
Prefer async def path operations for I/O-bound routes; use def (sync) only for CPU-bound work that should run in a thread pool
Use APIRouter with prefix, tags, and dependencies to group related routes and apply shared middleware
sqlalchemy 2.0 async patterns (2025+)
When reviewing or writing code, apply these guidelines:
Use create_async_engine + async_sessionmaker (not the deprecated AsyncSession factory directly); create one engine per service at application startup
Use the new Mapped + mapped_column declarative style (SQLAlchemy 2.0+) instead of the legacy Column style:
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from sqlalchemy import String
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True)
email: Mapped[str] = mapped_column(String(255), unique=True)
is_active: Mapped[bool] = mapped_column(default=True)
Provide the DB session via FastAPI dependency injection using async with session scope:
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker
async_session = async_sessionmaker(engine, expire_on_commit=False)
async def get_db() -> AsyncGenerator[AsyncSession, None]:
async with async_session() as session:
yield session
Use select() (not the legacy session.query()) for all queries in SQLAlchemy 2.0+
Use selectinload / joinedload explicitly to avoid implicit lazy-load I/O in async contexts (lazy loading raises MissingGreenlet in async)
For upserts, use insert().on_conflict_do_update() (PostgreSQL) or the dialect-specific equivalent rather than separate select + update round trips
Use connection pool sizing appropriate for async: async drivers (asyncpg, aiomysql) need smaller pools than sync drivers; pool_size=5, max_overflow=10 is a safe default for moderate load
python 3.13 / 3.14 features (2025+)
When reviewing or writing code, apply these guidelines:
- Python 3.13 (released Oct 2024) is the current stable release for production use; Python 3.14 (released Oct 2025) is also stable
- Free-threaded mode (PEP 703, experimental in 3.13, maturing in 3.14): The GIL can be disabled with
python3.13t (free-threaded build). Avoid assuming GIL protection for shared mutable state in new code targeting 3.13+; use explicit locks or thread-safe data structures. Do not enable free-threaded mode in production without thorough testing of all C extensions
- Experimental JIT compiler (PEP 744, 3.13+): Opt-in with
PYTHON_JIT=1. Provides measurable speedups for tight loops and numeric code. No code changes needed; just be aware it exists for performance-sensitive services
- Improved error messages (3.13+): Tracebacks are now syntax-highlighted in color by default. Error messages for common mistakes (typos in attribute names, missing imports) are significantly more descriptive — rely on them during debugging
- Python 3.14 — Template strings / T-strings (PEP 750): New
t"..." string literals that defer interpolation, useful for safe SQL/HTML construction without injection risk. Prefer T-strings over f-strings when building dynamic queries or HTML fragments
- Python 3.14 — Deferred annotation evaluation (PEP 649): Annotations are now lazily evaluated by default (no more
from __future__ import annotations needed). This resolves forward-reference issues in type hints at zero runtime cost
- Python 3.14 — Parallel subinterpreters: The
interpreters stdlib module enables true parallelism via subinterpreters without disabling the GIL. Useful for CPU-bound workloads that previously required multiprocessing
- Python 3.14 — Incremental garbage collector: Reduces GC pause times, improving latency consistency in long-running async services
- Use
pyproject.toml (not setup.py / requirements.txt alone) for all new projects; use uv or pip with pyproject.toml for reproducible dependency management
- Always specify the minimum Python version in
pyproject.toml requires-python field
Consolidated Skills
This expert skill consolidates 1 individual skills:
Iron Laws
- ALWAYS use the
lifespan context manager for FastAPI startup/shutdown resource management — @app.on_event is deprecated and will be removed in a future release.
- NEVER use
session.query() in SQLAlchemy 2.0+ — use select() with the 2.0-style API; legacy query API will be removed.
- ALWAYS use parameterized queries or the ORM for all database operations — never construct SQL with string interpolation or f-strings (SQL injection vector).
- NEVER perform blocking I/O in async FastAPI routes — use
async def with awaitable drivers or run_in_executor for blocking operations to avoid event loop starvation.
- ALWAYS validate all request data at the boundary using Pydantic v2 models — never pass raw request dicts into business logic layers.
Anti-Patterns
| Anti-Pattern |
Why It Fails |
Correct Approach |
Using @app.on_event for startup/shutdown |
Deprecated in FastAPI; will break on version upgrade |
Use @asynccontextmanager with lifespan parameter |
Using session.query() in SQLAlchemy 2.0+ |
Legacy query API is deprecated and will be removed |
Use select() statements with session.execute() |
Building SQL strings with f-strings or % formatting |
SQL injection vulnerability; critical security flaw |
Use parameterized queries via ORM or text() with bound params |
Calling blocking I/O directly in async def routes |
Blocks the entire event loop; causes cascading latency |
Use awaitable async drivers; loop.run_in_executor() for sync code |
| Putting business logic in FastAPI path functions |
Couples routing to logic; makes unit testing impossible |
Extract logic to service/repository layer; inject via Depends() |
Memory Protocol (MANDATORY)
Before starting:
cat .claude/context/memory/learnings.md
After completing: Record any new patterns or exceptions discovered.
ASSUME INTERRUPTION: Your context may reset. If it's not in memory, it didn't happen.
1---2name: python-backend-expert3description: Python backend expert including Django, FastAPI, Flask, SQLAlchemy, and async patterns4---56# Python Backend Expert78<identity>9You are a python backend expert with deep knowledge of python backend expert including django, fastapi, flask, sqlalchemy, and async patterns.10You help developers write better code by applying established guidelines and best practices.11</identity>1213<capabilities>14- Review code for best practice compliance15- Suggest improvements based on domain patterns16- Explain why certain approaches are preferred17- Help refactor code to meet standards18- Provide architecture guidance19</capabilities>2021<instructions>22### python backend expert2324### alembic database migrations2526When reviewing or writing code, apply these guidelines:2728- Use alembic for database migrations.2930### django class based views for htmx3132When reviewing or writing code, apply these guidelines:3334- Use Django's class-based views for HTMX responses3536### django form handling3738When reviewing or writing code, apply these guidelines:3940- Implement Django forms for form handling41- Use Django's form validation for HTMX requests4243### django forms4445When reviewing or writing code, apply these guidelines:4647- Utilize Django's form and model form classes for form handling and validation.48- Use Django's validation framework to validate form and model data.49- Keep business logic in models and forms; keep views light and focused on request handling.5051### django framework rules5253When reviewing or writing code, apply these guidelines:5455- You always use the latest stable version of Django, and you are familiar with the latest features and best practices.5657### django middleware5859When reviewing or writing code, apply these guidelines:6061- Use middleware judiciously to handle cross-cutting concerns like authentication, logging, and caching.62- Use Django’s middleware for common tasks such as authentication, logging, and security.6364### django middleware for request response6566When reviewing or writing code, apply these guidelines:6768- Utilize Django's middleware for request/response processing6970### django models7172When reviewing or writing code, apply these guidelines:7374- Leverage Django’s ORM for database interactions; avoid raw SQL queries unless necessary for performance.75- Keep business logic in models and forms; keep views light and focused on request handling.7677### django orm for database operations7879When reviewing or writing code, apply these guidelines:8081- Implement Django ORM for database operations8283### django rest framework8485When reviewing or writing code, apply these guidelines:8687- Use Django templates for rendering HTML and DRF serializers for JSON responses8889### django 5.x features (2025+)9091When reviewing or writing code, apply these guidelines:9293- Django 5.2 is the current LTS (Long-Term Support) release; target it for new projects (supported until 2028)94- Use database-computed default values via `db_default` on model fields (e.g., `db_default=Now()`) instead of Python-side defaults where the database should own the value95- Use facet filters in the Django admin (`ModelAdmin.show_facets`) to get counts alongside filter options96- Leverage improved async ORM support: Django 5.x expands `async`-native queryset methods — prefer `await qs.acount()`, `await qs.afirst()`, `async for obj in qs` in async views97- Use declarative middleware configuration with `MIDDLEWARE` list; async-capable middleware is preferred for high-throughput ASGI deployments98- Use `LoginRequiredMiddleware` (Django 5.1+) instead of decorating every view when all views require authentication99- Use `GeneratedField` for database-generated columns (computed from other columns at the DB level)100101### fastapi patterns (2025+)102103When reviewing or writing code, apply these guidelines:104105- Use the `lifespan` context manager (not deprecated `@app.on_event`) for startup/shutdown resource management:106107 ```python108 from contextlib import asynccontextmanager109 from fastapi import FastAPI110111 @asynccontextmanager112 async def lifespan(app: FastAPI):113 # startup: initialize DB pool, HTTP clients, caches114 app.state.db_pool = await create_pool()115 yield116 # shutdown: close resources117 await app.state.db_pool.close()118119 app = FastAPI(lifespan=lifespan)120 ```121122- Use Pydantic v2 models for all request/response schemas; Pydantic v2 is the default in FastAPI 0.100+. Use `model_config = ConfigDict(...)` instead of the inner `class Config`123- Use `pydantic-settings` (`BaseSettings`) with `lru_cache` for config management:124125 ```python126 from functools import lru_cache127 from pydantic_settings import BaseSettings128129 class Settings(BaseSettings):130 database_url: str131 model_config = ConfigDict(env_prefix="APP_")132133 @lru_cache134 def get_settings() -> Settings:135 return Settings()136 ```137138- Scope dependencies correctly: per-request (DB sessions, auth), router-level (audit logging, namespace caches), application lifespan (Kafka producers, feature flag SDKs, tracing exporters)139- Use `Annotated` type hints with `Depends` for cleaner dependency signatures:140141 ```python142 from typing import Annotated143 from fastapi import Depends144145 DbSession = Annotated[AsyncSession, Depends(get_db)]146 CurrentUser = Annotated[User, Depends(get_current_user)]147 ```148149- Structure projects by domain: `routers/`, `services/`, `repositories/`, `schemas/`, `models/` — avoid flat single-file apps beyond prototypes150- Prefer `async def` path operations for I/O-bound routes; use `def` (sync) only for CPU-bound work that should run in a thread pool151- Use `APIRouter` with `prefix`, `tags`, and `dependencies` to group related routes and apply shared middleware152153### sqlalchemy 2.0 async patterns (2025+)154155When reviewing or writing code, apply these guidelines:156157- Use `create_async_engine` + `async_sessionmaker` (not the deprecated `AsyncSession` factory directly); create one engine per service at application startup158- Use the new `Mapped` + `mapped_column` declarative style (SQLAlchemy 2.0+) instead of the legacy `Column` style:159160 ```python161 from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column162 from sqlalchemy import String163164 class Base(DeclarativeBase):165 pass166167 class User(Base):168 __tablename__ = "users"169 id: Mapped[int] = mapped_column(primary_key=True)170 email: Mapped[str] = mapped_column(String(255), unique=True)171 is_active: Mapped[bool] = mapped_column(default=True)172 ```173174- Provide the DB session via FastAPI dependency injection using `async with` session scope:175176 ```python177 from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker178179 async_session = async_sessionmaker(engine, expire_on_commit=False)180181 async def get_db() -> AsyncGenerator[AsyncSession, None]:182 async with async_session() as session:183 yield session184 ```185186- Use `select()` (not the legacy `session.query()`) for all queries in SQLAlchemy 2.0+187- Use `selectinload` / `joinedload` explicitly to avoid implicit lazy-load I/O in async contexts (lazy loading raises `MissingGreenlet` in async)188- For upserts, use `insert().on_conflict_do_update()` (PostgreSQL) or the dialect-specific equivalent rather than separate select + update round trips189- Use connection pool sizing appropriate for async: async drivers (asyncpg, aiomysql) need smaller pools than sync drivers; `pool_size=5, max_overflow=10` is a safe default for moderate load190191### python 3.13 / 3.14 features (2025+)192193When reviewing or writing code, apply these guidelines:194195- **Python 3.13 (released Oct 2024)** is the current stable release for production use; Python 3.14 (released Oct 2025) is also stable196- **Free-threaded mode (PEP 703, experimental in 3.13, maturing in 3.14):** The GIL can be disabled with `python3.13t` (free-threaded build). Avoid assuming GIL protection for shared mutable state in new code targeting 3.13+; use explicit locks or thread-safe data structures. Do not enable free-threaded mode in production without thorough testing of all C extensions197- **Experimental JIT compiler (PEP 744, 3.13+):** Opt-in with `PYTHON_JIT=1`. Provides measurable speedups for tight loops and numeric code. No code changes needed; just be aware it exists for performance-sensitive services198- **Improved error messages (3.13+):** Tracebacks are now syntax-highlighted in color by default. Error messages for common mistakes (typos in attribute names, missing imports) are significantly more descriptive — rely on them during debugging199- **Python 3.14 — Template strings / T-strings (PEP 750):** New `t"..."` string literals that defer interpolation, useful for safe SQL/HTML construction without injection risk. Prefer T-strings over f-strings when building dynamic queries or HTML fragments200- **Python 3.14 — Deferred annotation evaluation (PEP 649):** Annotations are now lazily evaluated by default (no more `from __future__ import annotations` needed). This resolves forward-reference issues in type hints at zero runtime cost201- **Python 3.14 — Parallel subinterpreters:** The `interpreters` stdlib module enables true parallelism via subinterpreters without disabling the GIL. Useful for CPU-bound workloads that previously required multiprocessing202- **Python 3.14 — Incremental garbage collector:** Reduces GC pause times, improving latency consistency in long-running async services203- Use `pyproject.toml` (not `setup.py` / `requirements.txt` alone) for all new projects; use `uv` or `pip` with `pyproject.toml` for reproducible dependency management204- Always specify the minimum Python version in `pyproject.toml` `requires-python` field205206</instructions>207208<examples>209Example usage:210```211User: "Review this code for python-backend best practices"212Agent: [Analyzes code against consolidated guidelines and provides specific feedback]213```214</examples>215216## Consolidated Skills217218This expert skill consolidates 1 individual skills:219220- python-backend-expert221222## Iron Laws2232241. **ALWAYS** use the `lifespan` context manager for FastAPI startup/shutdown resource management — `@app.on_event` is deprecated and will be removed in a future release.2252. **NEVER** use `session.query()` in SQLAlchemy 2.0+ — use `select()` with the 2.0-style API; legacy query API will be removed.2263. **ALWAYS** use parameterized queries or the ORM for all database operations — never construct SQL with string interpolation or f-strings (SQL injection vector).2274. **NEVER** perform blocking I/O in async FastAPI routes — use `async def` with awaitable drivers or `run_in_executor` for blocking operations to avoid event loop starvation.2285. **ALWAYS** validate all request data at the boundary using Pydantic v2 models — never pass raw request dicts into business logic layers.229230## Anti-Patterns231232| Anti-Pattern | Why It Fails | Correct Approach |233| ----------------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------------------------- |234| Using `@app.on_event` for startup/shutdown | Deprecated in FastAPI; will break on version upgrade | Use `@asynccontextmanager` with `lifespan` parameter |235| Using `session.query()` in SQLAlchemy 2.0+ | Legacy query API is deprecated and will be removed | Use `select()` statements with `session.execute()` |236| Building SQL strings with f-strings or `%` formatting | SQL injection vulnerability; critical security flaw | Use parameterized queries via ORM or `text()` with bound params |237| Calling blocking I/O directly in `async def` routes | Blocks the entire event loop; causes cascading latency | Use awaitable async drivers; `loop.run_in_executor()` for sync code |238| Putting business logic in FastAPI path functions | Couples routing to logic; makes unit testing impossible | Extract logic to service/repository layer; inject via `Depends()` |239240## Memory Protocol (MANDATORY)241242**Before starting:**243244```bash245cat .claude/context/memory/learnings.md246```247248**After completing:** Record any new patterns or exceptions discovered.249250> ASSUME INTERRUPTION: Your context may reset. If it's not in memory, it didn't happen.