| name | sqlmodel-expert |
| description | Advanced SQLModel patterns and comprehensive database migrations with Alembic. Use when creating SQLModel models, defining relationships (one-to-many, many-to-many, self-referential), setting up database migrations, optimizing queries, solving N+1 problems, implementing inheritance patterns, working with composite keys, creating indexes, performing data migrations, or troubleshooting Alembic issues. Triggers include "SQLModel", "Alembic migration", "database model", "relationship", "foreign key", "migration", "N+1 query", "query optimization", "database schema", or questions about ORM patterns. |
SQLModel Expert
Advanced SQLModel patterns and comprehensive Alembic migrations for production databases.
Quick Start
Define a Basic Model
from sqlmodel import Field, SQLModel
from typing import Optional
from datetime import datetime
class Task(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
title: str = Field(index=True)
description: Optional[str] = None
completed: bool = Field(default=False)
created_at: datetime = Field(default_factory=datetime.utcnow)
Initialize Database
cd backend
alembic upgrade head
from sqlmodel import create_engine
engine = create_engine("postgresql://user:pass@localhost/db")
SQLModel.metadata.create_all(engine)
Create Migration
cd backend
alembic revision --autogenerate -m "add user table"
alembic upgrade head
Core Topics
1. Advanced Model Patterns
- Relationships: One-to-many, many-to-many, self-referential
- Inheritance: Single table, joined table, polymorphism
- Validation: Pydantic validators, custom constraints
- Mixins: Timestamp, soft delete, reusable patterns
- Field Types: Enums, JSON, arrays, custom types
- Indexes: Single, composite, partial indexes
- Constraints: Unique, check, foreign key cascades
2. Comprehensive Migrations
- Alembic Setup: Configuration, env.py for SQLModel
- Creating Migrations: Autogenerate vs manual
- Schema Changes: Add/drop columns, rename, change types
- Data Migrations: Complex data transformations
- Production Workflow: Zero-downtime migrations
- Rollback Strategies: Safe downgrade patterns
- Troubleshooting: Common issues and solutions
3. Query Optimization
- N+1 Problem: Solutions with eager loading
- Query Patterns: Joins, aggregations, subqueries
- Performance: Indexes, batch operations, profiling
- Advanced Queries: Window functions, CTEs
- Bulk Operations: Insert, update, delete at scale
Common Patterns
One-to-Many Relationship
from typing import List, Optional
from sqlmodel import Field, Relationship, SQLModel
class Organization(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
resources: List["Resource"] = Relationship(back_populates="organization")
class Resource(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
organization_id: Optional[int] = Field(foreign_key="organization.id")
organization: Optional[Organization] = Relationship(back_populates="resources")
Many-to-Many with Link Table
class ResourceCategoryLink(SQLModel, table=True):
resource_id: int = Field(foreign_key="resource.id", primary_key=True)
category_id: int = Field(foreign_key="category.id", primary_key=True)
class Resource(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
categories: List["Category"] = Relationship(
back_populates="resources",
link_model=ResourceCategoryLink
)
class Category(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
resources: List[Resource] = Relationship(
back_populates="categories",
link_model=ResourceCategoryLink
)
Solving N+1 Query Problem
from sqlalchemy.orm import selectinload
resources = session.exec(select(Resource)).all()
for resource in resources:
org = resource.organization
statement = select(Resource).options(selectinload(Resource.organization))
resources = session.exec(statement).all()
for resource in resources:
org = resource.organization
Creating a Migration
class Resource(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
phone: str
def upgrade() -> None:
op.add_column('resource', sa.Column('phone', sa.String(), nullable=True))
def downgrade() -> None:
op.drop_column('resource', 'phone')
Vibe4Vets Specific Patterns
Trust Score Calculation
from sqlmodel import Field, SQLModel
from datetime import datetime
from typing import Optional
class Resource(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
source_id: Optional[int] = Field(foreign_key="source.id")
last_verified: Optional[datetime] = None
@property
def trust_score(self) -> float:
"""Calculate trust = reliability * freshness"""
if not self.source or not self.last_verified:
return 0.0
reliability = self.source.reliability_score
days_since_verified = (datetime.utcnow() - self.last_verified).days
freshness = max(0, 1 - (days_since_verified / 365))
return reliability * freshness
Full-Text Search with PostgreSQL
from sqlalchemy import Index, text
from sqlmodel import Field, SQLModel
class Resource(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
description: Optional[str] = None
__table_args__ = (
Index(
'ix_resource_search',
text("to_tsvector('english', name || ' ' || COALESCE(description, ''))"),
postgresql_using='gin'
),
)
Best Practices Checklist
Model Design
Relationships
Migrations
Troubleshooting Guide
Migration Issues
Problem: Alembic doesn't detect model changes
from app.models import Resource, Organization, Source
target_metadata = SQLModel.metadata
Problem: Failed migration
alembic current
alembic stamp head
alembic downgrade -1
alembic upgrade head
Query Performance
Problem: Slow queries
logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
explain = session.exec(text("EXPLAIN ANALYZE SELECT ...")).all()
Production Workflow
Development
- Modify SQLModel models
- Generate migration:
alembic revision --autogenerate -m "description"
- Review generated migration file
- Test migration locally
- Commit migration file
Production
- Backup database:
pg_dump mydb > backup.sql
- Deploy in maintenance window
- Run migrations:
alembic upgrade head
- Monitor logs and metrics
- Verify application functionality