From 3d02f906bec6389abca8a47ed1ad7301f268ff88 Mon Sep 17 00:00:00 2001 From: parkyugyeong Date: Sat, 23 Nov 2024 22:10:48 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=EA=B8=B0=EB=8A=A5=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/crud.py | 38 +++++++++++++ src/database.py | 14 +++++ src/main.py | 16 ++++++ .../TecheerPartnersApiSessionApplication.java | 13 ----- .../config/WebConfig.java | 18 ------ src/main/resources/application.properties | 10 ---- src/models.py | 9 +++ src/requirements.txt | 4 ++ src/routers/__init__.py | 0 src/routers/tasks.py | 56 +++++++++++++++++++ src/schemas.py | 17 ++++++ ...eerPartnersApiSessionApplicationTests.java | 13 ----- src/tests/test_tasks.py | 0 13 files changed, 154 insertions(+), 54 deletions(-) create mode 100644 src/crud.py create mode 100644 src/database.py create mode 100644 src/main.py delete mode 100644 src/main/java/com/example/techeer_partners_api_session/TecheerPartnersApiSessionApplication.java delete mode 100644 src/main/java/com/example/techeer_partners_api_session/config/WebConfig.java delete mode 100644 src/main/resources/application.properties create mode 100644 src/models.py create mode 100644 src/requirements.txt create mode 100644 src/routers/__init__.py create mode 100644 src/routers/tasks.py create mode 100644 src/schemas.py delete mode 100644 src/test/java/com/example/techeer_partners_api_session/TecheerPartnersApiSessionApplicationTests.java create mode 100644 src/tests/test_tasks.py diff --git a/src/crud.py b/src/crud.py new file mode 100644 index 0000000..d40b470 --- /dev/null +++ b/src/crud.py @@ -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 diff --git a/src/database.py b/src/database.py new file mode 100644 index 0000000..d1f3876 --- /dev/null +++ b/src/database.py @@ -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() diff --git a/src/main.py b/src/main.py new file mode 100644 index 0000000..cdb4bd7 --- /dev/null +++ b/src/main.py @@ -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) diff --git a/src/main/java/com/example/techeer_partners_api_session/TecheerPartnersApiSessionApplication.java b/src/main/java/com/example/techeer_partners_api_session/TecheerPartnersApiSessionApplication.java deleted file mode 100644 index dd01199..0000000 --- a/src/main/java/com/example/techeer_partners_api_session/TecheerPartnersApiSessionApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.example.techeer_partners_api_session; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class TecheerPartnersApiSessionApplication { - - public static void main(String[] args) { - SpringApplication.run(TecheerPartnersApiSessionApplication.class, args); - } - -} diff --git a/src/main/java/com/example/techeer_partners_api_session/config/WebConfig.java b/src/main/java/com/example/techeer_partners_api_session/config/WebConfig.java deleted file mode 100644 index bc617fa..0000000 --- a/src/main/java/com/example/techeer_partners_api_session/config/WebConfig.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.example.techeer_partners_api_session.config; - -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.CorsRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -@Configuration -public class WebConfig implements WebMvcConfigurer { - - @Override - public void addCorsMappings(CorsRegistry registry) { - registry.addMapping("/**") // 모든 경로에 대해 - .allowedOrigins("http://localhost:3000") // 프론트엔드 주소 (React 예시) - .allowedMethods("GET", "POST", "PUT", "DELETE") // 허용할 HTTP 메서드 - .allowedHeaders("*") // 모든 헤더 허용 - .allowCredentials(true); // 쿠키 등 인증 정보 허용 - } -} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index c7ffb1a..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1,10 +0,0 @@ -spring.application.name=techeer-partners-api-session - -# H2 -spring.datasource.url=jdbc:h2:mem:todolistdb -spring.datasource.driverClassName=org.h2.Driver -spring.datasource.username=user -spring.datasource.password=password -spring.jpa.database-platform=org.hibernate.dialect.H2Dialect -spring.h2.console.enabled=true -spring.h2.console.path=/h2-console diff --git a/src/models.py b/src/models.py new file mode 100644 index 0000000..ea4ca16 --- /dev/null +++ b/src/models.py @@ -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) diff --git a/src/requirements.txt b/src/requirements.txt new file mode 100644 index 0000000..0a4249c --- /dev/null +++ b/src/requirements.txt @@ -0,0 +1,4 @@ +fastapi +uvicorn +sqlalchemy +pydantic diff --git a/src/routers/__init__.py b/src/routers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/routers/tasks.py b/src/routers/tasks.py new file mode 100644 index 0000000..39fa5ce --- /dev/null +++ b/src/routers/tasks.py @@ -0,0 +1,56 @@ +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)): + crud.create_task(db, task) + return {"status": "success", "message": "할 일이 생성되었습니다."} + +# 전체 할 일 조회 +@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": "할 일이 삭제되었습니다."} diff --git a/src/schemas.py b/src/schemas.py new file mode 100644 index 0000000..7fb99be --- /dev/null +++ b/src/schemas.py @@ -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 + +class TaskResponse(BaseModel): + id: int + title: str + is_done: bool + + class Config: + from_attributes = True diff --git a/src/test/java/com/example/techeer_partners_api_session/TecheerPartnersApiSessionApplicationTests.java b/src/test/java/com/example/techeer_partners_api_session/TecheerPartnersApiSessionApplicationTests.java deleted file mode 100644 index 4d67ec1..0000000 --- a/src/test/java/com/example/techeer_partners_api_session/TecheerPartnersApiSessionApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.example.techeer_partners_api_session; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class TecheerPartnersApiSessionApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/src/tests/test_tasks.py b/src/tests/test_tasks.py new file mode 100644 index 0000000..e69de29 From 7167e4ecedd00419b31df3d06b3e765c6bad7913 Mon Sep 17 00:00:00 2001 From: parkyugyeong Date: Sat, 23 Nov 2024 23:52:21 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=EC=98=A4=EB=A5=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routers/tasks.py | 6 ++++-- src/test.db | Bin 0 -> 12288 bytes test.db | Bin 0 -> 12288 bytes 3 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 src/test.db create mode 100644 test.db diff --git a/src/routers/tasks.py b/src/routers/tasks.py index 39fa5ce..640d95b 100644 --- a/src/routers/tasks.py +++ b/src/routers/tasks.py @@ -18,11 +18,13 @@ def get_db(): finally: db.close() +# 할 일 생성 # 할 일 생성 @router.post("", response_model=TaskResponse, status_code=201) def create_task(task: TaskCreate, db: Session = Depends(get_db)): - crud.create_task(db, task) - return {"status": "success", "message": "할 일이 생성되었습니다."} + new_task = crud.create_task(db, task) + return new_task + # 전체 할 일 조회 @router.get("", response_model=list[TaskResponse]) diff --git a/src/test.db b/src/test.db new file mode 100644 index 0000000000000000000000000000000000000000..5c9d77f7f7bb464f0e7859a5c3349d4a40a87e41 GIT binary patch literal 12288 zcmeI#&r8EF6bJB^RFoBD-g_2Tz!fYN3k*gYbxpF<7?k% z<@k)opT0vt00Izz00bZa0SG_<0uX=z1pbXcEO(>BNECKaH!Hg;UDdv}rLFrhm>R8e z&9n4EKk-JEvy}TCd}Qm%IuLtN6p3}?s^_`y{1tsCf6nJBPV{gf9NF66nCnYzIL&fS zAClyl!;!OY-teO`(<}8mW81P`E*g%rEYT|MHs6}rjWPva>!SaLaMIQ0zUW6l00Izz y00bZa0SG_<0uX=z1R$`*0%7+y)c;%jhw(HBKmY;|fB*y_009U<00Izz0MR#0`$HiB literal 0 HcmV?d00001 diff --git a/test.db b/test.db new file mode 100644 index 0000000000000000000000000000000000000000..c354cb800650ad023ca49e1ef2e9e531b2697e5d GIT binary patch literal 12288 zcmeI&y=&V*7zXguhd(4+eltaMJLpnF$x_H%*%7I!A}5Ml>dClBDMwv9#G-`KC0ihC z{($@erBjEHDMQJWA!N!BI%No%I+RWwdM9kS4uwpG!gHWUkNutw^V?!Aru|;`V@|rJG7JL3d-VLq)tuC^q_XnPwnzYR5gA6PPKmY;|fB*y_ z009U<00Izzz<(pqGRyu$-{^~Rn(d0+K|Y+moeo4=+^u#J2ECAX;+60f*QUH1^I`{o zB+}-dWmJ6MH}xfjI*b7&~gvZ?;k6%R5W9~Y+$VVA} z86@pz!JiW`9i)?S##`NP6b7-{yqymow#U}GrFB!=U(>#)U-JF`GozpMo$ly{zR?w3(m9>cDV@+4Il_Vf1Rwwb z2tWV=5P$##AOHafK;WMWlq|z&G*o(?%6eU8t)|j-RXUE!YE@;WqOx38St_ZtZIza# J(k%YZ{~HH?fH?pF literal 0 HcmV?d00001