Add due date feature to Todo application

- Added due_date field to Todo model
- Updated schemas to include due_date field
- Created Alembic migration for the new field
- Added API endpoint to filter todos by due date range
- Updated README to document the new feature

🤖 Generated with BackendIM... (backend.im)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Automated Action 2025-05-13 05:14:03 +00:00
parent b5638b4c86
commit 1d7eac0ac7
5 changed files with 68 additions and 4 deletions

View File

@ -5,6 +5,8 @@ A RESTful API for a Todo application built with FastAPI and SQLite.
## Features
- Create, Read, Update, and Delete Todo items
- Due date assignment and tracking for todo items
- Filtering todos by due date range
- Health endpoint for application monitoring
- SQLite database with SQLAlchemy ORM
- Database migrations with Alembic
@ -17,6 +19,7 @@ A RESTful API for a Todo application built with FastAPI and SQLite.
- **GET /api/v1/todos/{id}**: Get a specific todo by ID
- **PUT /api/v1/todos/{id}**: Update a todo
- **DELETE /api/v1/todos/{id}**: Delete a todo
- **GET /api/v1/todos/due-date/**: Filter todos by due date range
## Getting Started

View File

@ -0,0 +1,24 @@
"""add due_date column to todo table
Revision ID: 002
Revises: 001
Create Date: 2025-05-13
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '002'
down_revision = '001'
branch_labels = None
depends_on = None
def upgrade() -> None:
op.add_column('todo', sa.Column('due_date', sa.DateTime(timezone=True), nullable=True))
def downgrade() -> None:
op.drop_column('todo', 'due_date')

View File

@ -1,6 +1,7 @@
from typing import Any, List
from fastapi import APIRouter, Depends, HTTPException, status
from typing import Any, List, Optional
from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.orm import Session
from datetime import datetime, date
from app import schemas
from app.models.todo import Todo
@ -33,6 +34,7 @@ def create_todo(
title=todo_in.title,
description=todo_in.description,
completed=todo_in.completed,
due_date=todo_in.due_date,
)
db.add(todo)
db.commit()
@ -97,7 +99,39 @@ def delete_todo(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Todo with ID {id} not found"
)
db.delete(todo)
db.commit()
return None
return None
@router.get("/due-date/", response_model=List[schemas.Todo])
def get_todos_by_due_date(
*,
db: Session = Depends(get_db),
start_date: Optional[date] = Query(None, description="Filter todos due on or after this date"),
end_date: Optional[date] = Query(None, description="Filter todos due on or before this date"),
skip: int = 0,
limit: int = 100,
) -> Any:
"""
Filter todos by due date range.
"""
query = db.query(Todo)
if start_date:
# Convert date to datetime with time at beginning of day
start_datetime = datetime.combine(start_date, datetime.min.time())
query = query.filter(Todo.due_date >= start_datetime)
if end_date:
# Convert date to datetime with time at end of day
end_datetime = datetime.combine(end_date, datetime.max.time())
query = query.filter(Todo.due_date <= end_datetime)
# Only return todos with due dates if filtering by date
if start_date or end_date:
query = query.filter(Todo.due_date.isnot(None))
todos = query.order_by(Todo.due_date.asc()).offset(skip).limit(limit).all()
return todos

View File

@ -8,5 +8,6 @@ class Todo(Base):
title = Column(String, index=True)
description = Column(String, nullable=True)
completed = Column(Boolean, default=False)
due_date = Column(DateTime(timezone=True), nullable=True)
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())

View File

@ -7,6 +7,7 @@ class TodoBase(BaseModel):
title: str
description: Optional[str] = None
completed: bool = False
due_date: Optional[datetime] = None
# Properties to receive on creation
class TodoCreate(TodoBase):
@ -16,6 +17,7 @@ class TodoCreate(TodoBase):
class TodoUpdate(TodoBase):
title: Optional[str] = None
completed: Optional[bool] = None
due_date: Optional[datetime] = None
# Properties shared by models stored in DB
class TodoInDBBase(TodoBase):