-
Notifications
You must be signed in to change notification settings - Fork 18
[A팀 박유경} 백엔드 API 과제제출 #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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 |
| 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() |
| 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.
This file was deleted.
| 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) | ||
| is_done = Column(Boolean, default=False) | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 요구사항에 따라 달라질 수 있겠지만 현재 요구사항에는 is_done을 통해 쿼리를 하는 경우가 많으므로 title 보다는 is_done에 인덱스를 설정해주는 것이 좋을 것 같습니다! |
||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. requirements.txt를 통해 의존 라이브러리 관리를 해주고 계십니다. 혹시 앞으로도 파이썬 계열 프레임워크를 사용하실 계획이라면 requirements.txt 보다는 라이브러리별로 버전까지 관리해주는 poetry의 사용법을 한번 익혀보시는 걸 추천드립니다 ㅎㅎ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| fastapi | ||
| uvicorn | ||
| sqlalchemy | ||
| pydantic |
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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": "할 일이 삭제되었습니다."} |
| 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 | ||
|
|
||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
This file was deleted.
There was a problem hiding this comment.
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 조건을 걸지 않아도 인덱스를 생성합니다 😄