Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions src/crud.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from sqlalchemy.orm import Session
from src.models import Task
from src.schemas import TaskCreate, TaskUpdate

def get_tasks(db: Session):
return db.query(Task).all()

def get_tasks_by_status(db: Session, is_done: bool):
return db.query(Task).filter(Task.is_done == is_done).all()

def get_task(db: Session, task_id: int):
return db.query(Task).filter(Task.id == task_id).first()

def create_task(db: Session, task: TaskCreate):
db_task = Task(**task.dict())
db.add(db_task)
db.commit()
db.refresh(db_task)
return db_task


def update_task(db: Session, task_id: int, task_update: TaskUpdate):
db_task = get_task(db, task_id)
if db_task:
if task_update.title is not None:
db_task.title = task_update.title
if task_update.is_done is not None:
db_task.is_done = task_update.is_done
db.commit()
db.refresh(db_task)
return db_task

def delete_task(db: Session, task_id: int):
db_task = get_task(db, task_id)
if db_task:
db.delete(db_task)
db.commit()
return db_task
14 changes: 14 additions & 0 deletions src/database.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base, sessionmaker # 변경된 경로로 import

# 데이터베이스 URL
DATABASE_URL = "sqlite:///./test.db"

# 데이터베이스 엔진
engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})

# 세션 로컬 생성
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

# Declarative Base 클래스 생성
Base = declarative_base()
16 changes: 16 additions & 0 deletions src/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from fastapi import FastAPI
from src.routers import tasks
from src.database import Base, engine

# 데이터베이스 초기화
Base.metadata.create_all(bind=engine)

# FastAPI 앱 생성
app = FastAPI(
title="Todo List API",
description="FastAPI를 사용한 Todo List API",
version="1.0.0"
)

# Task 라우터 추가
app.include_router(tasks.router)

This file was deleted.

This file was deleted.

10 changes: 0 additions & 10 deletions src/main/resources/application.properties

This file was deleted.

9 changes: 9 additions & 0 deletions src/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from sqlalchemy import Column, Integer, String, Boolean
from src.database import Base

class Task(Base):
__tablename__ = 'tasks'

id = Column(Integer, primary_key=True, index=True)
title = Column(String, index=True)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

id 필드는 primary_key를 통해 기본키로 설정되었으므로 명시적으로 index=true 조건을 걸지 않아도 인덱스를 생성합니다 😄

is_done = Column(Boolean, default=False)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요구사항에 따라 달라질 수 있겠지만 현재 요구사항에는 is_done을 통해 쿼리를 하는 경우가 많으므로 title 보다는 is_done에 인덱스를 설정해주는 것이 좋을 것 같습니다!

4 changes: 4 additions & 0 deletions src/requirements.txt

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

requirements.txt를 통해 의존 라이브러리 관리를 해주고 계십니다. 혹시 앞으로도 파이썬 계열 프레임워크를 사용하실 계획이라면 requirements.txt 보다는 라이브러리별로 버전까지 관리해주는 poetry의 사용법을 한번 익혀보시는 걸 추천드립니다 ㅎㅎ
저도 예전에는 requirements.txt로 관리했던 경험이 있지만 라이브러리끼리 버전 문제로 호환이 되지 않는 경우 직접 에러를 살펴보고 구글링해서 고쳤던 기억이 납니다. poetry를 사용한다면 이런 문제를 사전에 방지할 수 있어 추천드립니다! 😄

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fastapi
uvicorn
sqlalchemy
pydantic
Empty file added src/routers/__init__.py
Empty file.
58 changes: 58 additions & 0 deletions src/routers/tasks.py

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

현재는 api의 수가 많지 않아 직접 응답을 작성해서 반환하는 것이 큰 단점이라 볼 수는 없겠지만 따로 응답 객체를 만들어서 일관성 있는 응답 형식을 제공해보는 것을 추천 드립니다!

ex)

class ApiResponse(BaseModel):
    status: str  
    message: str  
    data: Optional[Any] = None  

Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from src.database import SessionLocal
from src.schemas import TaskCreate, TaskUpdate, TaskResponse
from src import crud


router = APIRouter(
prefix="/tasks",
tags=["Tasks"]
)

# DB 세션 의존성
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()

# 할 일 생성
# 할 일 생성
@router.post("", response_model=TaskResponse, status_code=201)
def create_task(task: TaskCreate, db: Session = Depends(get_db)):
new_task = crud.create_task(db, task)
return new_task


# 전체 할 일 조회
@router.get("", response_model=list[TaskResponse])
def read_tasks(db: Session = Depends(get_db)):
return crud.get_tasks(db)

# 완료된 일 조회
@router.get("/completed", response_model=list[TaskResponse])
def read_completed_tasks(db: Session = Depends(get_db)):
return crud.get_tasks_by_status(db, is_done=True)

# 미완료된 일 조회
@router.get("/incomplete", response_model=list[TaskResponse])
def read_incomplete_tasks(db: Session = Depends(get_db)):
return crud.get_tasks_by_status(db, is_done=False)

# 할 일 수정
@router.patch("/{id}", response_model=TaskResponse)
def update_task(id: int, task_update: TaskUpdate, db: Session = Depends(get_db)):
task = crud.update_task(db, id, task_update)
if not task:
raise HTTPException(status_code=404, detail="Task not found")
return {"status": "success", "message": "할 일이 수정되었습니다."}

# 할 일 삭제
@router.delete("/{id}")
def delete_task(id: int, db: Session = Depends(get_db)):
task = crud.delete_task(db, id)
if not task:
raise HTTPException(status_code=404, detail="Task not found")
return {"status": "success", "message": "할 일이 삭제되었습니다."}
17 changes: 17 additions & 0 deletions src/schemas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from pydantic import BaseModel

class TaskCreate(BaseModel):
title: str
is_done: bool = False

class TaskUpdate(BaseModel):
title: str = None
is_done: bool = None

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

클라이언트에 의해 입력된 값만 수정 될 수 있도록 기본값을 None으로 설정해주신 것 좋습니다 👍

class TaskResponse(BaseModel):
id: int
title: str
is_done: bool

class Config:
from_attributes = True
Binary file added src/test.db
Binary file not shown.

This file was deleted.

Empty file added src/tests/test_tasks.py
Empty file.
Binary file added test.db
Binary file not shown.