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:
parent
34f86c8479
commit
a00c823bd1
@ -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:
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user