Add advanced filtering, sorting, and pagination to Todo list endpoint

This commit is contained in:
Automated Action 2025-05-17 23:43:11 +00:00
parent 25fd3c49f2
commit 38273684c4
2 changed files with 53 additions and 5 deletions

View File

@ -5,6 +5,7 @@ A deadass simple Todo API built with FastAPI and SQLite. This project provides a
## Features ## Features
- RESTful API endpoints for Todo resource (Create, Read, Update, Delete) - RESTful API endpoints for Todo resource (Create, Read, Update, Delete)
- Advanced filtering, sorting, and pagination capabilities
- SQLite database with SQLAlchemy ORM - SQLite database with SQLAlchemy ORM
- Database migrations with Alembic - Database migrations with Alembic
- Health check endpoint - Health check endpoint
@ -66,7 +67,17 @@ The API will be available at http://localhost:8000
- `GET /health` - Check API and database health - `GET /health` - Check API and database health
### Todo Management ### Todo Management
- `GET /api/v1/todos` - Get all todos (with optional pagination and filtering) - `GET /api/v1/todos` - Get all todos (with advanced filtering, sorting, and pagination)
- Filtering options:
- `completed`: Filter by completion status (true/false)
- `created_after`: Filter todos created on or after date (YYYY-MM-DD)
- `created_before`: Filter todos created on or before date (YYYY-MM-DD)
- Sorting options:
- `sort_by`: Field to sort by (id, title, created_at, updated_at)
- `sort_order`: Sort direction (asc, desc)
- Pagination:
- `skip`: Number of items to skip
- `limit`: Maximum number of items to return
- `GET /api/v1/todos/{todo_id}` - Get a specific todo by ID - `GET /api/v1/todos/{todo_id}` - Get a specific todo by ID
- `POST /api/v1/todos` - Create a new todo - `POST /api/v1/todos` - Create a new todo
- `PUT /api/v1/todos/{todo_id}` - Update an existing todo - `PUT /api/v1/todos/{todo_id}` - Update an existing todo

View File

@ -1,6 +1,8 @@
from typing import List, Optional from typing import List, Optional
from datetime import datetime, date
from fastapi import APIRouter, Depends, HTTPException, status, Response, Query from fastapi import APIRouter, Depends, HTTPException, status, Response, Query
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from sqlalchemy import desc, asc
from app.db.database import get_db from app.db.database import get_db
from app.models.todo import Todo as TodoModel from app.models.todo import Todo as TodoModel
@ -31,23 +33,58 @@ def read_todos(
skip: int = 0, skip: int = 0,
limit: int = 100, limit: int = 100,
completed: Optional[bool] = Query(None, description="Filter by completion status"), completed: Optional[bool] = Query(None, description="Filter by completion status"),
created_after: Optional[date] = Query(None, description="Filter todos created after this date (YYYY-MM-DD)"),
created_before: Optional[date] = Query(None, description="Filter todos created before this date (YYYY-MM-DD)"),
sort_by: str = Query("id", description="Field to sort by (id, title, created_at, updated_at)"),
sort_order: str = Query("asc", description="Sort order (asc or desc)"),
db: Session = Depends(get_db) db: Session = Depends(get_db)
): ):
""" """
Get all todo items with optional filtering. Get all todo items with optional filtering, sorting, and pagination.
- **skip**: Number of items to skip (pagination) - **skip**: Number of items to skip (pagination)
- **limit**: Maximum number of items to return - **limit**: Maximum number of items to return (pagination)
- **completed**: Optional filter by completion status - **completed**: Optional filter by completion status (true/false)
- **created_after**: Filter todos created on or after this date (format: YYYY-MM-DD)
- **created_before**: Filter todos created on or before this date (format: YYYY-MM-DD)
- **sort_by**: Field to sort by (options: id, title, created_at, updated_at)
- **sort_order**: Sort order (options: asc, desc)
Returns a list of todo items. Returns a list of todo items.
""" """
query = db.query(TodoModel) query = db.query(TodoModel)
# Apply filter if completed parameter is provided # Apply filters
if completed is not None: if completed is not None:
query = query.filter(TodoModel.completed == completed) query = query.filter(TodoModel.completed == completed)
if created_after:
# Convert date to datetime with time at start of day (00:00:00)
start_datetime = datetime.combine(created_after, datetime.min.time())
query = query.filter(TodoModel.created_at >= start_datetime)
if created_before:
# Convert date to datetime with time at end of day (23:59:59)
end_datetime = datetime.combine(created_before, datetime.max.time())
query = query.filter(TodoModel.created_at <= end_datetime)
# Apply sorting
if sort_by not in ["id", "title", "created_at", "updated_at"]:
sort_by = "id" # Default to id if invalid field provided
if sort_order.lower() not in ["asc", "desc"]:
sort_order = "asc" # Default to ascending if invalid order provided
# Get the attribute to sort by
sort_attr = getattr(TodoModel, sort_by)
# Apply sorting direction
if sort_order.lower() == "desc":
query = query.order_by(desc(sort_attr))
else:
query = query.order_by(asc(sort_attr))
# Apply pagination
todos = query.offset(skip).limit(limit).all() todos = query.offset(skip).limit(limit).all()
return todos return todos