home / skills / 0xdarkmatter / claude-mods / python-database-patterns
/skills/python-database-patterns
This skill helps you implement robust Python database patterns with SQLAlchemy 2.0, AsyncIO support, and repository patterns for reliable data access.
npx playbooks add skill 0xdarkmatter/claude-mods --skill python-database-patternsReview the files below or copy the command above to add this skill to your agents.
---
name: python-database-patterns
description: "SQLAlchemy and database patterns for Python. Triggers on: sqlalchemy, database, orm, migration, alembic, async database, connection pool, repository pattern, unit of work."
compatibility: "SQLAlchemy 2.0+, Python 3.10+. Async requires asyncpg (PostgreSQL) or aiosqlite."
allowed-tools: "Read Write Bash"
depends-on: [python-typing-patterns, python-async-patterns]
related-skills: [python-fastapi-patterns]
---
# Python Database Patterns
SQLAlchemy 2.0 and database best practices.
## SQLAlchemy 2.0 Basics
```python
from sqlalchemy import create_engine, select
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(100))
email: Mapped[str] = mapped_column(String(255), unique=True)
is_active: Mapped[bool] = mapped_column(default=True)
# Create engine and tables
engine = create_engine("postgresql://user:pass@localhost/db")
Base.metadata.create_all(engine)
# Query with 2.0 style
with Session(engine) as session:
stmt = select(User).where(User.is_active == True)
users = session.execute(stmt).scalars().all()
```
## Async SQLAlchemy
```python
from sqlalchemy.ext.asyncio import (
AsyncSession,
async_sessionmaker,
create_async_engine,
)
from sqlalchemy import select
# Async engine
engine = create_async_engine(
"postgresql+asyncpg://user:pass@localhost/db",
echo=False,
pool_size=5,
max_overflow=10,
)
# Session factory
async_session = async_sessionmaker(engine, expire_on_commit=False)
# Usage
async with async_session() as session:
result = await session.execute(select(User).where(User.id == 1))
user = result.scalar_one_or_none()
```
## Model Relationships
```python
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship, Mapped, mapped_column
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
# One-to-many
posts: Mapped[list["Post"]] = relationship(back_populates="author")
class Post(Base):
__tablename__ = "posts"
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
author_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
# Many-to-one
author: Mapped["User"] = relationship(back_populates="posts")
```
## Common Query Patterns
```python
from sqlalchemy import select, and_, or_, func
# Basic select
stmt = select(User).where(User.is_active == True)
# Multiple conditions
stmt = select(User).where(
and_(
User.is_active == True,
User.age >= 18
)
)
# OR conditions
stmt = select(User).where(
or_(User.role == "admin", User.role == "moderator")
)
# Ordering and limiting
stmt = select(User).order_by(User.created_at.desc()).limit(10)
# Aggregates
stmt = select(func.count(User.id)).where(User.is_active == True)
# Joins
stmt = select(User, Post).join(Post, User.id == Post.author_id)
# Eager loading
from sqlalchemy.orm import selectinload
stmt = select(User).options(selectinload(User.posts))
```
## FastAPI Integration
```python
from fastapi import Depends, FastAPI
from sqlalchemy.ext.asyncio import AsyncSession
from typing import Annotated
async def get_db() -> AsyncGenerator[AsyncSession, None]:
async with async_session() as session:
yield session
DB = Annotated[AsyncSession, Depends(get_db)]
@app.get("/users/{user_id}")
async def get_user(user_id: int, db: DB):
result = await db.execute(select(User).where(User.id == user_id))
user = result.scalar_one_or_none()
if not user:
raise HTTPException(status_code=404)
return user
```
## Quick Reference
| Operation | SQLAlchemy 2.0 Style |
|-----------|---------------------|
| Select all | `select(User)` |
| Filter | `.where(User.id == 1)` |
| First | `.scalar_one_or_none()` |
| All | `.scalars().all()` |
| Count | `select(func.count(User.id))` |
| Join | `.join(Post)` |
| Eager load | `.options(selectinload(User.posts))` |
## Additional Resources
- `./references/sqlalchemy-async.md` - Async patterns, session management
- `./references/connection-pooling.md` - Pool configuration, health checks
- `./references/transactions.md` - Transaction patterns, isolation levels
- `./references/migrations.md` - Alembic setup, migration strategies
## Assets
- `./assets/alembic.ini.template` - Alembic configuration template
---
## See Also
**Prerequisites:**
- `python-typing-patterns` - Mapped types and annotations
- `python-async-patterns` - Async database sessions
**Related Skills:**
- `python-fastapi-patterns` - Dependency injection for DB sessions
- `python-pytest-patterns` - Database fixtures and testing
This skill provides practical SQLAlchemy 2.0 patterns and database best practices for Python projects, covering sync and async engines, ORM models, queries, relationships, and FastAPI integration. It bundles recommended patterns for connection pooling, migrations (Alembic), and transaction handling to help teams build reliable data access layers. The content focuses on concrete examples and quick references that you can apply directly in applications.
It inspects common database tasks and provides idiomatic SQLAlchemy 2.0 code for model declarations, queries, relationships, and session usage both synchronous and asynchronous. It also documents integration points (FastAPI DI), connection pool configuration, and migration strategies with Alembic. The skill groups patterns into snippets, quick-reference operations, and linked deeper references for sessions, pooling, transactions, and migrations.
Should I use sync or async SQLAlchemy?
Choose async for async frameworks (FastAPI async endpoints) and when using async drivers like asyncpg; use sync for simple scripts or when the app is synchronous.
How do I avoid N+1 queries?
Use eager loading options such as selectinload or joinedload in your select statements to fetch related collections efficiently.