diff --git a/fastapi_app/app/.gitignore b/fastapi_app/app/.gitignore new file mode 100644 index 00000000..bd7590f7 --- /dev/null +++ b/fastapi_app/app/.gitignore @@ -0,0 +1,3 @@ +/venv +/__pycache__ +*.pyc \ No newline at end of file diff --git a/fastapi_app/app/Readme.md b/fastapi_app/app/Readme.md new file mode 100644 index 00000000..549becf3 --- /dev/null +++ b/fastapi_app/app/Readme.md @@ -0,0 +1,60 @@ +# 📝 Personal Task Tracker API (FastAPI) + +A simple **FastAPI-based Task Tracker** that allows users to create, view, complete, and delete tasks. +This project is designed for **learning FastAPI, SQLAlchemy, and basic CRUD operations**. + +--- + +## 🚀 Features + +- Create a task +- View all tasks +- Mark a task as completed +- Delete a task +- SQLite database (easy setup) +- Clean and simple API design + +> ⚠️ Authentication is mocked using a **fake user ID** to keep the app simple. + +--- + +## 🧱 Tech Stack + +- **FastAPI** +- **SQLAlchemy** +- **SQLite** +- **Uvicorn** + +--- + +## 📁 Project Structure + +app/ +├── main.py # FastAPI routes +├── database.py # Database connection +├── models.py # SQLAlchemy models +├── schemas.py # Pydantic schemas + + + +--- + +## ⚙️ Installation + +### 1️⃣ Create a virtual environment (optional) +```bash +python -m venv venv +source venv/bin/activate # Mac/Linux +venv\Scripts\activate # Windows + + +2️⃣ Install dependencies +pip install fastapi uvicorn sqlalchemy + +▶️ Run the Application +uvicorn main:app --reload + + +API: http://127.0.0.1:8000 + +Swagger Docs: http://127.0.0.1:8000/docs \ No newline at end of file diff --git a/fastapi_app/app/database.py b/fastapi_app/app/database.py new file mode 100644 index 00000000..47bbf730 --- /dev/null +++ b/fastapi_app/app/database.py @@ -0,0 +1,12 @@ +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker, declarative_base + +DATABASE_URL = "sqlite:///./tasks.db" + +engine = create_engine( + DATABASE_URL, connect_args={"check_same_thread": False} +) + +SessionLocal = sessionmaker(bind=engine) + +Base = declarative_base() diff --git a/fastapi_app/app/main.py b/fastapi_app/app/main.py new file mode 100644 index 00000000..78132787 --- /dev/null +++ b/fastapi_app/app/main.py @@ -0,0 +1,64 @@ +from fastapi import FastAPI, Depends, HTTPException +from sqlalchemy.orm import Session + +from database import SessionLocal, engine +from models import Base, Task +from schemas import TaskCreate, TaskResponse + +Base.metadata.create_all(bind=engine) + +app = FastAPI() + + +# DB dependency +def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close() + + +# Fake user (to keep it simple) +FAKE_USER_ID = 1 + + +@app.post("/tasks", response_model=TaskResponse) +def create_task(task: TaskCreate, db: Session = Depends(get_db)): + new_task = Task( + title=task.title, + user_id=FAKE_USER_ID + ) + db.add(new_task) + db.commit() + db.refresh(new_task) + return new_task + + +@app.get("/tasks", response_model=list[TaskResponse]) +def get_tasks(db: Session = Depends(get_db)): + return db.query(Task).filter(Task.user_id == FAKE_USER_ID).all() + + +@app.put("/tasks/{task_id}") +def complete_task(task_id: int, db: Session = Depends(get_db)): + task = db.query(Task).filter(Task.id == task_id).first() + + if not task: + raise HTTPException(status_code=404, detail="Task not found") + + task.is_completed = True + db.commit() + return {"message": "Task completed"} + + +@app.delete("/tasks/{task_id}") +def delete_task(task_id: int, db: Session = Depends(get_db)): + task = db.query(Task).filter(Task.id == task_id).first() + + if not task: + raise HTTPException(status_code=404, detail="Task not found") + + db.delete(task) + db.commit() + return {"message": "Task deleted"} diff --git a/fastapi_app/app/models.py b/fastapi_app/app/models.py new file mode 100644 index 00000000..e430a25a --- /dev/null +++ b/fastapi_app/app/models.py @@ -0,0 +1,18 @@ +from sqlalchemy import Column, Integer, String, Boolean, ForeignKey +from database import Base + +class User(Base): + __tablename__ = "users" + + id = Column(Integer, primary_key=True, index=True) + email = Column(String, unique=True, index=True) + password = Column(String) + + +class Task(Base): + __tablename__ = "tasks" + + id = Column(Integer, primary_key=True, index=True) + title = Column(String) + is_completed = Column(Boolean, default=False) + user_id = Column(Integer, ForeignKey("users.id")) diff --git a/fastapi_app/app/schemas.py b/fastapi_app/app/schemas.py new file mode 100644 index 00000000..97d6056a --- /dev/null +++ b/fastapi_app/app/schemas.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel + +class TaskCreate(BaseModel): + title: str + + +class TaskResponse(BaseModel): + id: int + title: str + is_completed: bool + + class Config: + from_attributes = True diff --git a/fastapi_app/app/tasks.db b/fastapi_app/app/tasks.db new file mode 100644 index 00000000..06a03b03 Binary files /dev/null and b/fastapi_app/app/tasks.db differ