fastapi-sqlmodel-crud-patterns
Standard patterns for building and maintaining CRUD APIs with FastAPI and SQLModel: models, routers, database access, and error handling in a reusable way.
$ Instalar
git clone https://github.com/majiayu000/claude-skill-registry /tmp/claude-skill-registry && cp -r /tmp/claude-skill-registry/skills/data/fastapi-sqlmodel-crud-patterns ~/.claude/skills/claude-skill-registry// tip: Run this command in your terminal to install the skill
name: fastapi-sqlmodel-crud-patterns description: > Standard patterns for building and maintaining CRUD APIs with FastAPI and SQLModel: models, routers, database access, and error handling in a reusable way.
FastAPI + 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:
db.pyor similar: session creation and engine.models.pyormodels/: SQLModel models.routers/orroutes/: FastAPI routers per resource.main.py: FastAPI app entrypoint registering routers.
The exact filenames can differ between projects; the patterns stay the same.
Resource and endpoint conventions
-
Each logical resource (e.g.
Task,Item,User) should have its own router module, for example:routers/tasks.pywith aAPIRouter(prefix="/tasks", tags=["tasks"]).
-
Typical REST endpoints per resource:
GET /<resource>→ list items.POST /<resource>→ create item.GET /<resource>/{id}→ get single item.PUT /<resource>/{id}→ replace item.PATCH /<resource>/{id}→ partial update (optional).DELETE /<resource>/{id}→ delete item. [web:53][web:59]
-
Resource names should be plural in paths (
/tasks,/users), with singular nouns used in model/type names (Task,User).
Models and schemas
-
Use SQLModel models for database tables, with:
- Primary key fields (
idor similar). - Optional timestamps (e.g.
created_at,updated_at) when useful. - Reasonable defaults and constraints (e.g.
nullable,max_length).
- Primary key fields (
-
When needed, define separate Pydantic/SQLModel schemas for:
- Create input (e.g.
TaskCreate) – fields required for creation. - Update input (e.g.
TaskUpdate) – optional fields for partial updates. - Response model (e.g.
TaskRead) – what the API returns.
- 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:
get_session()indb.pythat yields aSessionobject.
-
Use
Depends(get_session)in routers to access the database. -
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 (
GETcollection):- Return a list of items, optionally with pagination, filtering, or sorting based on query parameters.
- Avoid returning unbounded, huge result sets when possible.
-
Get (
GETsingle):- Fetch the item by primary key.
- If not found, raise
HTTPException(status_code=404)with a clear message.
-
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
HTTPExceptionwith appropriate status codes and simple, safe error messages. [web:53][web:59] -
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:
response_model=TaskReadorList[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
limitandoffsetor page/size pairs. - 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:
db.pyor equivalent – engine andget_sessiondependency.models.pyormodels/– SQLModel models for resources.routers/orroutes/– resource-specific routers.
If these files are missing, propose creating them using these patterns rather than inventing a new, ad-hoc CRUD style for each resource.
Repository
