Claude-skill-registry fastapi-sqlmodel-crud-patterns
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/fastapi-sqlmodel-crud-patterns" ~/.claude/skills/majiayu000-claude-skill-registry-fastapi-sqlmodel-crud-patterns && rm -rf "$T"
skills/data/fastapi-sqlmodel-crud-patterns/SKILL.mdFastAPI + SQLModel CRUD Patterns Skill
When to use this Skill
Use this Skill whenever you are:
- Creating or modifying CRUD (Create, Read, Update, Delete) endpoints in a FastAPI application that uses SQLModel for persistence.
- Designing new resources (e.g. Task, UserProfile, Project, Order) and their REST endpoints.
- Refactoring existing API code to be more consistent and reliable.
- Adding tests or changing database access patterns related to CRUD.
This Skill must work for any FastAPI + SQLModel project, not just a single repository.
Core goals
- Keep CRUD code consistent, predictable, and easy to reuse across many projects.
- Separate concerns:
- Models (SQLModel) in one place.
- Routers (FastAPI endpoints) in another.
- Database session management in a dedicated module.
- Use clear REST semantics (HTTP verbs, status codes, resource paths).
- Provide strong typing via SQLModel and Pydantic models.
- Handle errors and not-found cases cleanly, without crashes. [web:53][web:59]
Architecture assumptions
- Web framework: FastAPI.
- ORM: SQLModel (sync or async, but pick one style per project).
- Database: Any SQL database supported by SQLModel (e.g. PostgreSQL). [web:53][web:57]
- Structure:
or similar: session creation and engine.db.py
ormodels.py
: SQLModel models.models/
orrouters/
: FastAPI routers per resource.routes/
: FastAPI app entrypoint registering routers.main.py
The exact filenames can differ between projects; the patterns stay the same.
Resource and endpoint conventions
-
Each logical resource (e.g.
,Task
,Item
) should have its own router module, for example:User
with arouters/tasks.py
.APIRouter(prefix="/tasks", tags=["tasks"])
-
Typical REST endpoints per resource:
→ list items.GET /<resource>
→ create item.POST /<resource>
→ get single item.GET /<resource>/{id}
→ replace item.PUT /<resource>/{id}
→ partial update (optional).PATCH /<resource>/{id}
→ delete item. [web:53][web:59]DELETE /<resource>/{id}
-
Resource names should be plural in paths (
,/tasks
), with singular nouns used in model/type names (/users
,Task
).User
Models and schemas
-
Use SQLModel models for database tables, with:
- Primary key fields (
or similar).id - Optional timestamps (e.g.
,created_at
) when useful.updated_at - Reasonable defaults and constraints (e.g.
,nullable
).max_length
- Primary key fields (
-
When needed, define separate Pydantic/SQLModel schemas for:
- Create input (e.g.
) – fields required for creation.TaskCreate - Update input (e.g.
) – optional fields for partial updates.TaskUpdate - Response model (e.g.
) – what the API returns.TaskRead
- Create input (e.g.
-
Avoid exposing internal-only fields (e.g. secrets) in response models.
Database session handling
-
Provide a shared dependency for DB sessions, for example:
inget_session()
that yields adb.py
object.Session
-
Use
in routers to access the database.Depends(get_session) -
Do not create database engines or sessions directly inside routers or endpoint functions. Keep connection logic centralized. [web:53][web:57]
CRUD behaviour patterns
For each resource, the default CRUD behaviour should follow this pattern:
-
Create (
):POST- Validate input using a dedicated schema if needed.
- Construct the SQLModel instance from the validated data.
- Add and commit the instance using the shared session.
- Refresh the instance to return updated fields (e.g. autoincrement id).
-
List (
collection):GET- Return a list of items, optionally with pagination, filtering, or sorting based on query parameters.
- Avoid returning unbounded, huge result sets when possible.
-
Get (
single):GET- Fetch the item by primary key.
- If not found, raise
with a clear message.HTTPException(status_code=404)
-
Update (
/PUT
):PATCH- Load the existing item; if not found, return 404.
- Apply allowed changes from the input schema.
- Commit and refresh before returning the updated item.
-
Delete (
):DELETE- Load the existing item; if not found, return 404.
- Either hard-delete or soft-delete depending on the project’s rules.
- Return appropriate status (e.g. 204 No Content for hard delete).
Error handling
-
Never let database or Python exceptions leak directly to clients. Use
with appropriate status codes and simple, safe error messages. [web:53][web:59]HTTPException -
Common error cases:
- Resource not found → 404.
- Validation errors → 422 (FastAPI will handle many of these).
- Unauthorized/forbidden (if auth is applied) → 401/403.
-
Log details server-side if needed, but keep responses simple.
Typing and response models
-
Always declare response models in router decorators when practical:
orresponse_model=TaskRead
.List[TaskRead]
-
This improves:
- OpenAPI docs.
- Type checking in clients.
- Clarity of what each endpoint returns.
-
Avoid returning raw dicts or mixing data shapes; keep responses consistent.
Filtering, sorting, and pagination (optional)
-
When adding filtering/sorting:
- Use query parameters (e.g.
,status
,sort_by
).order - Document default behaviours and limits in the resource spec.
- Use query parameters (e.g.
-
For pagination:
- Use standard patterns like
andlimit
or page/size pairs.offset - Enforce maximum limits to avoid performance issues.
- Use standard patterns like
Things to avoid
- Creating engines or sessions inside endpoint functions.
- Mixing business logic, validation, and database operations in large monolithic functions; prefer small helpers where appropriate.
- Returning raw SQLModel instances that include internal fields that should not be exposed.
- Using inconsistent status codes for the same error conditions.
References inside the repo
When present, this Skill should align with:
or equivalent – engine anddb.py
dependency.get_session
ormodels.py
– SQLModel models for resources.models/
orrouters/
– resource-specific routers.routes/
If these files are missing, propose creating them using these patterns rather than inventing a new, ad-hoc CRUD style for each resource.