From a05d19017ec8e6be07f40c59f680ec6b55979a86 Mon Sep 17 00:00:00 2001 From: Automated Action Date: Fri, 16 May 2025 04:30:03 +0000 Subject: [PATCH] Add priority levels feature to Todo items - Added priority field (low, medium, high) to Todo model - Created migration for priority field addition - Updated API schemas to include priority - Added filtering by priority in GET todos endpoint - Updated README to reflect new features --- README.md | 8 +++-- app/api/schemas.py | 9 ++++++ app/api/todos.py | 30 ++++++++++++++---- app/models/todo.py | 10 +++++- migrations/versions/add_priority_field.py | 37 +++++++++++++++++++++++ 5 files changed, 84 insertions(+), 10 deletions(-) create mode 100644 migrations/versions/add_priority_field.py diff --git a/README.md b/README.md index 3d13ec7..364b38b 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ A simple Todo API built with FastAPI and SQLite. ## Features - Create, Read, Update, and Delete Todo items +- Priority levels (Low, Medium, High) for todo items +- Filter todo items by priority - SQLite database with SQLAlchemy ORM - Database migrations with Alembic - API documentation with Swagger UI and ReDoc @@ -32,10 +34,10 @@ A simple Todo API built with FastAPI and SQLite. ## API Endpoints -- `GET /api/todos`: Get all todo items -- `POST /api/todos`: Create a new todo item +- `GET /api/todos`: Get all todo items (optional query parameter `priority` to filter by priority) +- `POST /api/todos`: Create a new todo item with optional priority level - `GET /api/todos/{todo_id}`: Get a specific todo item -- `PUT /api/todos/{todo_id}`: Update a todo item +- `PUT /api/todos/{todo_id}`: Update a todo item (including its priority) - `DELETE /api/todos/{todo_id}`: Delete a todo item - `GET /health`: Check application health diff --git a/app/api/schemas.py b/app/api/schemas.py index 94cabd1..97d6199 100644 --- a/app/api/schemas.py +++ b/app/api/schemas.py @@ -1,12 +1,20 @@ from pydantic import BaseModel from datetime import datetime from typing import Optional +from enum import Enum + + +class PriorityLevel(str, Enum): + LOW = "low" + MEDIUM = "medium" + HIGH = "high" class TodoBase(BaseModel): title: str description: Optional[str] = None completed: bool = False + priority: PriorityLevel = PriorityLevel.MEDIUM class TodoCreate(TodoBase): @@ -17,6 +25,7 @@ class TodoUpdate(BaseModel): title: Optional[str] = None description: Optional[str] = None completed: Optional[bool] = None + priority: Optional[PriorityLevel] = None class TodoResponse(TodoBase): diff --git a/app/api/todos.py b/app/api/todos.py index a8c737e..8871182 100644 --- a/app/api/todos.py +++ b/app/api/todos.py @@ -1,8 +1,8 @@ -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 app.database.config import get_db -from app.models.todo import Todo +from app.models.todo import Todo, PriorityLevel from app.api.schemas import TodoCreate, TodoResponse, TodoUpdate router = APIRouter() @@ -19,9 +19,27 @@ def create_todo(todo: TodoCreate, db: Session = Depends(get_db)): @router.get("/", response_model=List[TodoResponse]) -def read_todos(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): - """Get all todo items""" - todos = db.query(Todo).offset(skip).limit(limit).all() +def read_todos( + skip: int = 0, + limit: int = 100, + priority: Optional[PriorityLevel] = Query( + None, description="Filter todos by priority level" + ), + db: Session = Depends(get_db), +): + """ + Get all todo items with optional filtering by priority + + - **skip**: Number of records to skip + - **limit**: Maximum number of records to return + - **priority**: Optional filter by priority level (low, medium, high) + """ + query = db.query(Todo) + + if priority: + query = query.filter(Todo.priority == priority) + + todos = query.offset(skip).limit(limit).all() return todos diff --git a/app/models/todo.py b/app/models/todo.py index 70c1eea..72dfca5 100644 --- a/app/models/todo.py +++ b/app/models/todo.py @@ -1,8 +1,15 @@ -from sqlalchemy import Column, Integer, String, Boolean, DateTime +from sqlalchemy import Column, Integer, String, Boolean, DateTime, Enum from sqlalchemy.sql import func +import enum from app.database.config import Base +class PriorityLevel(str, enum.Enum): + LOW = "low" + MEDIUM = "medium" + HIGH = "high" + + class Todo(Base): __tablename__ = "todos" @@ -10,5 +17,6 @@ class Todo(Base): title = Column(String, index=True) description = Column(String, nullable=True) completed = Column(Boolean, default=False) + priority = Column(Enum(PriorityLevel), default=PriorityLevel.MEDIUM, nullable=False) created_at = Column(DateTime, default=func.now()) updated_at = Column(DateTime, default=func.now(), onupdate=func.now()) diff --git a/migrations/versions/add_priority_field.py b/migrations/versions/add_priority_field.py new file mode 100644 index 0000000..004e5c8 --- /dev/null +++ b/migrations/versions/add_priority_field.py @@ -0,0 +1,37 @@ +"""add priority field to todos + +Revision ID: 002 +Revises: 001 +Create Date: 2023-08-21 + +""" + +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(): + # Create priority_level enum type + priority_type = sa.Enum("low", "medium", "high", name="prioritylevel") + priority_type.create(op.get_bind()) + + # Add priority column to todos table with default value of 'medium' + op.add_column( + "todos", + sa.Column("priority", priority_type, nullable=False, server_default="medium"), + ) + + +def downgrade(): + # Drop priority column + op.drop_column("todos", "priority") + + # Drop the enum type + sa.Enum(name="prioritylevel").drop(op.get_bind())