From 76dc7f1991ab391a0d8a840874b68b6974ea4a65 Mon Sep 17 00:00:00 2001 From: Automated Action Date: Tue, 13 May 2025 00:55:47 +0000 Subject: [PATCH] Add search feature for todos - Add /api/todos/search endpoint with text search capability - Implement filtering by completed status - Include pagination and result count - Update documentation with new endpoint details generated with BackendIM... (backend.im) --- README.md | 18 +++++++++++++++++- app/routers/todo.py | 43 ++++++++++++++++++++++++++++++++++++++++--- app/schemas/todo.py | 11 +++++++++-- 3 files changed, 66 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 4c9959b..cb6b270 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ This is a FastAPI application that implements a simple Todo API. ## Features - Create, read, update, and delete todo items +- Search todos by text query with optional filtering - Health check endpoint - SQLite database for data storage - FastAPI automatic documentation @@ -41,8 +42,23 @@ The server will start at http://localhost:8000 ## API Endpoints - `GET /api/todos`: List all todos +- `GET /api/todos/search`: Search todos by text query - `POST /api/todos`: Create a new todo - `GET /api/todos/{todo_id}`: Get a specific todo - `PUT /api/todos/{todo_id}`: Update a todo - `DELETE /api/todos/{todo_id}`: Delete a todo -- `GET /health`: Check application health \ No newline at end of file +- `GET /health`: Check application health + +### Search Endpoint + +The search endpoint allows searching todos by text query with additional filters: + +``` +GET /api/todos/search?q=search_term&completed=true&skip=0&limit=10 +``` + +Parameters: +- `q`: (required) Search text to match in title or description +- `completed`: (optional) Filter by completion status (true/false) +- `skip`: (optional) Number of records to skip for pagination +- `limit`: (optional) Maximum number of records to return \ No newline at end of file diff --git a/app/routers/todo.py b/app/routers/todo.py index f61a0aa..7cb87b1 100644 --- a/app/routers/todo.py +++ b/app/routers/todo.py @@ -1,10 +1,11 @@ -from fastapi import APIRouter, Depends, HTTPException, status +from fastapi import APIRouter, Depends, HTTPException, status, Query from sqlalchemy.orm import Session -from typing import List +from typing import List, Optional +from sqlalchemy import or_ from app.database import get_db from app.models.todo import Todo as TodoModel -from app.schemas.todo import Todo, TodoCreate, TodoUpdate +from app.schemas.todo import Todo, TodoCreate, TodoUpdate, TodoSearchResults router = APIRouter() @@ -13,6 +14,42 @@ def get_todos(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): todos = db.query(TodoModel).offset(skip).limit(limit).all() return todos +@router.get("/search", response_model=TodoSearchResults) +def search_todos( + q: str = Query(..., description="Search query string"), + completed: Optional[bool] = Query(None, description="Filter by completion status"), + skip: int = 0, + limit: int = 100, + db: Session = Depends(get_db) +): + query = db.query(TodoModel) + + # Apply search filter (search in title and description) + query = query.filter( + or_( + TodoModel.title.contains(q), + TodoModel.description.contains(q) + ) + ) + + # Apply completion status filter if provided + if completed is not None: + query = query.filter(TodoModel.completed == completed) + + # Count total results + total = query.count() + + # Apply pagination + todos = query.offset(skip).limit(limit).all() + + return { + "todos": todos, + "total": total, + "skip": skip, + "limit": limit, + "query": q + } + @router.post("/", response_model=Todo, status_code=status.HTTP_201_CREATED) def create_todo(todo: TodoCreate, db: Session = Depends(get_db)): db_todo = TodoModel(**todo.dict()) diff --git a/app/schemas/todo.py b/app/schemas/todo.py index 33a9a52..1bb05f6 100644 --- a/app/schemas/todo.py +++ b/app/schemas/todo.py @@ -1,6 +1,6 @@ from pydantic import BaseModel from datetime import datetime -from typing import Optional +from typing import Optional, List class TodoBase(BaseModel): title: str @@ -21,4 +21,11 @@ class Todo(TodoBase): updated_at: Optional[datetime] = None class Config: - orm_mode = True \ No newline at end of file + orm_mode = True + +class TodoSearchResults(BaseModel): + todos: List[Todo] + total: int + skip: int + limit: int + query: str \ No newline at end of file