Add search functionality to find todos by title or description

- Add search parameter to get_todos CRUD function
- Add search parameter to main todos endpoint
- Create dedicated /search endpoint for title/description search
- Update README with new search functionality
- Fix datetime import issue in todo_stats function

generated with BackendIM... (backend.im)
This commit is contained in:
Automated Action 2025-05-13 04:20:44 +00:00
parent 34f86c8479
commit a00c823bd1
3 changed files with 45 additions and 2 deletions

View File

@ -10,6 +10,7 @@ A simple Todo API application built with FastAPI and SQLite. This RESTful API pr
- Priority levels (low, medium, high) - Priority levels (low, medium, high)
- Due dates for task deadlines - Due dates for task deadlines
- Task completion tracking with completion timestamps - Task completion tracking with completion timestamps
- Search functionality to find todos by title or description content
- Advanced filtering capabilities: - Advanced filtering capabilities:
- Filter by category - Filter by category
- Filter by priority - Filter by priority
@ -52,6 +53,7 @@ simpletodoapplication/
### Todo Operations ### Todo Operations
- **GET /api/v1/todos/** - Get all todos with filtering options - **GET /api/v1/todos/** - Get all todos with filtering options
- **POST /api/v1/todos/** - Create a new todo - **POST /api/v1/todos/** - Create a new todo
- **GET /api/v1/todos/search** - Search todos by title or description content
- **GET /api/v1/todos/{todo_id}** - Get a specific todo - **GET /api/v1/todos/{todo_id}** - Get a specific todo
- **PUT /api/v1/todos/{todo_id}** - Update a todo - **PUT /api/v1/todos/{todo_id}** - Update a todo
- **DELETE /api/v1/todos/{todo_id}** - Delete a todo - **DELETE /api/v1/todos/{todo_id}** - Delete a todo
@ -68,6 +70,7 @@ simpletodoapplication/
The GET /api/v1/todos/ endpoint supports the following query parameters: The GET /api/v1/todos/ endpoint supports the following query parameters:
- **search** - Search within title and description fields
- **category** - Filter todos by category - **category** - Filter todos by category
- **priority** - Filter by priority level (low, medium, high) - **priority** - Filter by priority level (low, medium, high)
- **completed** - Filter by completion status (true/false) - **completed** - Filter by completion status (true/false)
@ -78,6 +81,10 @@ The GET /api/v1/todos/ endpoint supports the following query parameters:
- **skip** - Number of records to skip (for pagination) - **skip** - Number of records to skip (for pagination)
- **limit** - Maximum number of records to return (for pagination) - **limit** - Maximum number of records to return (for pagination)
The GET /api/v1/todos/search endpoint requires the following parameter:
- **q** - Search query string (required) - searches in both title and description fields
## Setup and Running ## Setup and Running
1. Install dependencies: 1. Install dependencies:

View File

@ -20,6 +20,7 @@ def read_todos(
completed: Optional[bool] = None, completed: Optional[bool] = None,
due_before: Optional[datetime] = None, due_before: Optional[datetime] = None,
due_after: Optional[datetime] = None, due_after: Optional[datetime] = None,
search: Optional[str] = None,
sort_by: str = "created_at", sort_by: str = "created_at",
sort_desc: bool = True, sort_desc: bool = True,
db: Session = Depends(get_db) db: Session = Depends(get_db)
@ -30,6 +31,7 @@ def read_todos(
- Filter by priority level - Filter by priority level
- Filter by completion status - Filter by completion status
- Filter by due date (before/after) - Filter by due date (before/after)
- Search in title and description
- Sort by any field - Sort by any field
- Pagination - Pagination
""" """
@ -42,6 +44,7 @@ def read_todos(
completed=completed, completed=completed,
due_before=due_before, due_before=due_before,
due_after=due_after, due_after=due_after,
search=search,
sort_by=sort_by, sort_by=sort_by,
sort_desc=sort_desc sort_desc=sort_desc
) )
@ -54,6 +57,30 @@ def create_todo(todo: TodoCreate, db: Session = Depends(get_db)):
return crud.create_todo(db=db, todo=todo) return crud.create_todo(db=db, todo=todo)
@router.get("/search", response_model=List[Todo])
def search_todos(
q: str = Query(..., min_length=1, description="Search query for title or description"),
skip: int = 0,
limit: int = 100,
sort_by: str = "created_at",
sort_desc: bool = True,
db: Session = Depends(get_db)
):
"""
Search todos by title or description content
Returns todos where the title or description contains the search query
"""
todos = crud.get_todos(
db=db,
skip=skip,
limit=limit,
search=q,
sort_by=sort_by,
sort_desc=sort_desc
)
return todos
@router.get("/stats", response_model=Dict[str, Any]) @router.get("/stats", response_model=Dict[str, Any])
def get_todo_stats(db: Session = Depends(get_db)): def get_todo_stats(db: Session = Depends(get_db)):
"""Get statistics about todos including: """Get statistics about todos including:

View File

@ -20,6 +20,7 @@ def get_todos(
completed: Optional[bool] = None, completed: Optional[bool] = None,
due_before: Optional[datetime] = None, due_before: Optional[datetime] = None,
due_after: Optional[datetime] = None, due_after: Optional[datetime] = None,
search: Optional[str] = None,
sort_by: str = "created_at", sort_by: str = "created_at",
sort_desc: bool = True sort_desc: bool = True
) -> List[Todo]: ) -> List[Todo]:
@ -45,6 +46,14 @@ def get_todos(
if due_after: if due_after:
query = query.filter(Todo.due_date >= due_after) query = query.filter(Todo.due_date >= due_after)
# Apply text search if provided
if search:
search_term = f"%{search}%"
query = query.filter(
(Todo.title.ilike(search_term)) |
(Todo.description.ilike(search_term))
)
# Apply sorting # Apply sorting
if hasattr(Todo, sort_by): if hasattr(Todo, sort_by):
sort_column = getattr(Todo, sort_by) sort_column = getattr(Todo, sort_by)
@ -133,14 +142,14 @@ def get_todo_stats(db: Session) -> Dict[str, Any]:
).count() ).count()
# Get completed todos in last 24 hours # Get completed todos in last 24 hours
yesterday = now - datetime.timedelta(days=1) yesterday = now - timedelta(days=1)
completed_last_24h = db.query(Todo).filter( completed_last_24h = db.query(Todo).filter(
Todo.completion_date > yesterday, Todo.completion_date > yesterday,
Todo.completed == True Todo.completed == True
).count() ).count()
# Get completed todos in last 7 days # Get completed todos in last 7 days
last_week = now - datetime.timedelta(days=7) last_week = now - timedelta(days=7)
completed_last_week = db.query(Todo).filter( completed_last_week = db.query(Todo).filter(
Todo.completion_date > last_week, Todo.completion_date > last_week,
Todo.completed == True Todo.completed == True