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
- RESTful API endpoints for Todo resource (Create, Read, Update, Delete)
- Advanced filtering, sorting, and pagination capabilities
- SQLite database with SQLAlchemy ORM
- Database migrations with Alembic
- Health check endpoint
@ -66,7 +67,17 @@ The API will be available at http://localhost:8000
- `GET /health` - Check API and database health
### 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
- `POST /api/v1/todos` - Create a new todo
- `PUT /api/v1/todos/{todo_id}` - Update an existing todo

View File

@ -1,6 +1,8 @@
from typing import List, Optional
from datetime import datetime, date
from fastapi import APIRouter, Depends, HTTPException, status, Response, Query
from sqlalchemy.orm import Session
from sqlalchemy import desc, asc
from app.db.database import get_db
from app.models.todo import Todo as TodoModel
@ -31,23 +33,58 @@ def read_todos(
skip: int = 0,
limit: int = 100,
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)
):
"""
Get all todo items with optional filtering.
Get all todo items with optional filtering, sorting, and pagination.
- **skip**: Number of items to skip (pagination)
- **limit**: Maximum number of items to return
- **completed**: Optional filter by completion status
- **limit**: Maximum number of items to return (pagination)
- **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.
"""
query = db.query(TodoModel)
# Apply filter if completed parameter is provided
# Apply filters
if completed is not None:
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()
return todos