Skip to content

Instantly share code, notes, and snippets.

@rhoboro
Last active January 16, 2026 02:20
Show Gist options
  • Select an option

  • Save rhoboro/b2ee5b832f0557d65504b3220390ad8c to your computer and use it in GitHub Desktop.

Select an option

Save rhoboro/b2ee5b832f0557d65504b3220390ad8c to your computer and use it in GitHub Desktop.
FastAPI Minimal CRUD Template
"""FastAPI Minimal CRUD Template
```bash
uv add 'fastapi[standard]'
# Paste this file into main.py
uv run fastapi dev
```
```bash
curl -X GET http://localhost:8000/api/todos
curl -X GET http://localhost:8000/api/todos/N
curl -X POST -H 'content-type: application/json' -d '{"title": "new todo"}' http://localhost:8000/api/todos
curl -X PUT -H 'content-type: application/json' -d '{"title": "updated todo", "status": "IN_PROGRESS"}' http://localhost:8000/api/todos/N
curl -X DELETE http://localhost:8000/api/todos/N
```
"""
from enum import StrEnum
from fastapi import FastAPI, status
from fastapi.exceptions import HTTPException
from pydantic import BaseModel as _BaseModel
from pydantic import ConfigDict
IN_MEMORY_DB: dict[int, Todo] = {}
class Status(StrEnum):
NEW = "NEW"
IN_PROGRESS = "IN_PROGRESS"
COMPLETED = "COMPLETED"
class BaseModel(_BaseModel):
model_config = ConfigDict(frozen=True)
class Todo(BaseModel):
id: int
title: str
status: Status
class ListTodosResponse(BaseModel):
todos: list[Todo]
class CreateTodoRequest(BaseModel):
title: str
class UpdateTodoRequest(BaseModel):
title: str
status: Status
app = FastAPI()
@app.get("/")
async def index() -> dict:
return {"message": "hello"}
@app.get("/api/todos")
async def list_todos() -> ListTodosResponse:
return ListTodosResponse(todos=[todo for todo in IN_MEMORY_DB.values()])
@app.post("/api/todos", status_code=status.HTTP_201_CREATED)
async def create_todo(data: CreateTodoRequest) -> Todo:
next_id = max(IN_MEMORY_DB) + 1 if IN_MEMORY_DB else 0
todo = Todo(id=next_id, title=data.title, status=Status.NEW)
IN_MEMORY_DB[next_id] = todo
return todo
@app.get("/api/todos/{todo_id}")
async def get_todo(todo_id: int) -> Todo:
todo = IN_MEMORY_DB.get(todo_id, None)
if not todo:
raise HTTPException(404)
return todo
@app.put("/api/todos/{todo_id}")
async def update_todo(todo_id: int, data: UpdateTodoRequest) -> Todo:
todo = IN_MEMORY_DB.pop(todo_id, None)
if not todo:
raise HTTPException(404)
new_todo = todo.model_copy(update=dict(title=data.title, status=data.status))
IN_MEMORY_DB[todo.id] = new_todo
return new_todo
@app.delete("/api/todos/{todo_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_todo(todo_id: int) -> None:
if todo_id in IN_MEMORY_DB:
del IN_MEMORY_DB[todo_id]
return None
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment