앞 단계 참조 링크:
- 프로젝트 소개 및 환경 구축: 2024.04.05 - [Web 개발/FAST API (인프런 강의 내용)] - 1 실습1 GET API 전체조회
- 1 실습1 GET API ToDo 전체 조회: 2024.04.05 - [Web 개발/FAST API (인프런 강의 내용)] - 1 실습1 GET API 전체조회
- 1 실습2 GET API ToDo 단일 조회: 2024.04.09 - [Web 개발/FAST API (인프런 강의 내용)] - 1 실습2 GET API 단일조회
- 1 실습3 POST API ToDo 생성: 2024.04.15 - [Web 개발/FAST API (인프런 강의 내용)] - 1 실습3 POST API todo 생성
현재 파일 내용:
# /todos/src/main.py 내용
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
# 첫 화면 API
@app.get("/")
def health_check_handler():
return {"ping": "pong"}
# POST 생성을 위해 사용자로부터 전달받을 request 클래스 생성
class CreateToDoRequest(BaseModel):
id: int
contents: str
is_done: bool
# 데이터베이스 역할하는 딕셔너리 생성
todo_data = {
1: {
"id": 1,
"content": "실전! FastAPI 섹션 0 수강",
"is_done": True,
},
2: {
"id": 2,
"content": "실전! FastAPI 섹션 1 수강",
"is_done": False,
},
3: {
"id": 3,
"content": "실전! FastAPI 섹션 2 수강",
"is_done": False,
},
}
# GET Medthod 사용하여 전체 조회 API
@app.get("/todos")
def get_todos_handler(order: str | None = None):
rt = list(todo_data.values())
if order and order == "DESC":
return rt[::-1]
return rt
# GET Medthod 사용하여 단일 조회 API
@app.get("/todos/{todo_id}")
def get_todo_handler(todo_id: int):
return todo_data.get(todo_id, {})
# POST Medthod 사용하여 todo 생성 API
@app.post("/todos")
def create_todos_handler(request: CreateToDoRequest):
todo_data[request.id] = request.dict()
return todo_data[request.id]
04 기존 ToDo 수정하기 (PATCH Method 사용)
- PATCH Method를 이용해 기존에 있는 ToDo를 업데이트/수정하는 API 만들기
1. main.py에 쓰기
1) fastapi의 Body 참조하기
# todos > src > main.py
from fastapi import FastAPI, Body # 추가됨
from pydantic import BaseModel
...
2) PATCH Method Mapping 및 해당 path에 PATCH 요청을 보내는 API 생성
# todos > src > main.py
from fastapi import FastAPI, Body # 추가됨
from pydantic import BaseModel
...
@app.patch("/todos/{todos_id}")
def update_todo_handler(
todo_id: int,
is_done: bool = Body(..., embed=True)
):
todo = todo_data.get(todo_id)
if todo:
todo["is_done"] = is_done
return todo
return {}
- @app.patch("/todos/{todos_id}")
- app에 PATCH Method를 매핑
- todos 에 {todo_id}를 path로 받음
- def update_todo_handler(
- update_todo_handler 라는 함수(핸들러) 생성
- todo_id: int,
- todo_id 값을 int 형태로 받음
- is_done: bool = Body(..., embed=True)
- is_done 값을 bool 형태로 받음
- = Body(..., embed=True)
- 사용자의 todo의 달성 여부를 수정/업데이트 해주기 위해선 사용자로부터 request body로 is_done 값을 받아야 됨
- 앞서 (참조: 1 실습3 POST API ToDo 생성) 새로운 todo를 생성할 때처럼 3개의 컬럼 ('id', 'contents', 'is_done')을 업데이트할 것이 아니라 하나 (i.e., 'is_done')만 받을 것
- = Body(..., embed=True)를 적어줄 시 class 생성할 필요 없이 FastAPI에서 하나의 컬럼 값 (여기선 is_done)을 request body로 사용 가능
- 즉, is_done 값을 request body에 전달했을 때 이 is_done으로 들어오게 될 것(?)
- todo = todo_data.get(todo_id)
- 역할: todo_id로 todo 조회하기
- 기존의 todo_data에서 get Method 사용하여 todo_id를 통해 가져온 걸 todo에 넣음
- if todo:
- todo가 있을 경우
- todo["is_done"] = is_done
- 기존에 있는 todo의 is_done 값을 사용자의 요청으로 받은 is_done 값으로 수정
- return todo
- 수정된 데이터 반환
- return { }
- todo가 없을 경우 빈 딕셔너리 반환
2. FastAPI 웹 서버 자동 재시작 (--reload 옵션 사용)
- 웹 서버 실행 후 코드 변경 시 변경사항을 SwaggerUI에 반영하기 위해선 웹 서버 재시작 (uvicorn 종료 후 다시 실행) 필수
- reload 옵션 사용 시 변화가 감지되면 자동으로 서버를 FastAPI가 재시작 됨
- 방금 수정한 main.py를 저장 (ctrl + S) 하면 자동으로 재시작되어 변경사항이 반영됨
- 우선 시작 안했으면 시작하기
$ cd /c/Users/관리자/Desktop/projects/todos/src
$ uvicorn main:app --reload
INFO: Will watch for changes in these directories: ['C:\\Users\\관리자\\Desktop\\projects\\todos\\src']
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [11092] using StatReload
INFO: Started server process [13676]
INFO: Waiting for application startup.
INFO: Application startup complete.
- 시작 후 문서를 변경했으면 저장하기
# 변경된 main.py를 저장하면 다음이 터미널에 출력됨
WARNING: StatReload detected changes in 'main.py'. Reloading...
INFO: Started server process [17024]
INFO: Waiting for application startup.
INFO: Application startup complete.
3. SwaggerUI 및 화면 확인
1) Swagger 문서 확인
- 브라우저에 http://127.0.0.1:8000/docs 입력 또는 새로고침 시
- PATCH API가 추가된 것 확인
- PATCH 클릭 시 request body도 예시와 함께 문서 반영되어 있는 것 확인
- 다만, Responses에 대해서는 typing을 적용 안 해줬기에 아직 정상적으로 적용되지 않음 (추후에 바꿔볼 것임)
2) Swagger 문서에서 PATCH API 실습
- 전체 todo 목록 확인
- GET /todos Get Todos Handler > Try it out > Execute 하여 전체 목록 확인
- 'id'값 = 2인 todo의 'is_done' 값 수정하기
- PATCH /todos/{todo_id} Update Todo Handler > Try it out 클릭
- todo_id 값에 2 입력
- Request body에 {"is_done": true} 입력
- Execute 클릭 시
- Curl을 보면 PATCH Method의 /todos/2로 요청이 들어간 것을 확인
- Server Response를 보면 'id'=2인 todo의 'is_done' 값이 true로 수정된 것 확인
- 존재하지 않는 todo의 'is_done' 값 수정해보기
- PATCH /todos/{todo_id} Update Todo Handler > Try it out 클릭
- todo_id 값에 4 입력
- Request body에 {"is_done": true} 입력
- Execute 클릭 시
- Server Response를 보면 빈 딕셔너리 반환된 것 확인
주의※
- 상태코드
- 일반적으로 잘못된 path 처리에 대한 요청 (예, 지금과 같이 없는 todo의 값을 수정 등) 시 404 처리를 하지만 강의에선 아직 상태 메시지/코드에 대해 배우지 않아 지금은 빈 딕셔너리로 반환하는 것으로 처리
- 데이터베이스
- 앞서 <1 실습3 POST API ToDo 생성>에서 "id":4인 todo를 생성했는데 PATCH 했을 때에는 없다고 나오는 이유:
- todo를 database에 저장하지 않고 todo_data라는 딕셔너리를 이용해서 메모리에서 사용하고 있음
- 즉, 서버를 내렸다 올리면 그 때마다 메모리에 새로 쓰여진 값들이 refresh가 됨
- 즉, 코드로 적은 "id": 1, 2, 3번의 todo들만 남게 되고 서버가 내렸다 올라가면 우리가 동적으로 추가한 "id": 4의 todo는 남아있지 않음
- 그러므로 일반적인 경우 이런 작업을 database로 처리하여 새로 추가된 데이터나 변경된 데이터를 영속적으로 관리함
- 하지만 강의에선 아직 database에 대해 배우지 않아 지금은 서버를 내리고 올렸을 경우 "id": 1, 2, 3만 남아있음
- 추후 (section 2)에 database로 데이터 수정사항 영구적 저장 방법에 대해 배울것임
- 앞서 <1 실습3 POST API ToDo 생성>에서 "id":4인 todo를 생성했는데 PATCH 했을 때에는 없다고 나오는 이유:
이때까지의 코드들:
# .../todos/src/main.py 내용
from fastapi import FastAPI, Body
from pydantic import BaseModel
app = FastAPI()
# 첫 화면 API
@app.get("/")
def health_check_handler():
return {"ping": "pong"}
# POST 생성을 위해 사용자로부터 전달받을 request 클래스 생성
class CreateToDoRequest(BaseModel):
id: int
contents: str
is_done: bool
# 데이터베이스 역할하는 딕셔너리 생성
todo_data = {
1: {
"id": 1,
"content": "실전! FastAPI 섹션 0 수강",
"is_done": True,
},
2: {
"id": 2,
"content": "실전! FastAPI 섹션 1 수강",
"is_done": False,
},
3: {
"id": 3,
"content": "실전! FastAPI 섹션 2 수강",
"is_done": False,
},
}
# GET Method 사용하여 전체 조회 API
@app.get("/todos")
def get_todos_handler(order: str | None = None):
rt = list(todo_data.values())
if order and order == "DESC":
return rt[::-1]
return rt
# GET Method 사용하여 단일 조회 API
@app.get("/todos/{todo_id}")
def get_todo_handler(todo_id: int):
return todo_data.get(todo_id, {})
# POST Medthod 사용하여 todo 생성 API
@app.post("/todos")
def create_todos_handler(request: CreateToDoRequest):
todo_data[request.id] = request.dict()
return todo_data[request.id]
# PATCH Method 사용하여 is_done 값 수정 API
@app.patch("/todos/{todo_id}")
def update_todo_handler(
todo_id: int,
is_done: bool = Body(..., embed=True)
):
todo = todo_data.get(todo_id)
if todo:
todo["is_done"] = is_done
return todo
return {}
'Web 개발 > FAST API (인프런 강의 내용)' 카테고리의 다른 글
1 실습6 ERROR 처리 (0) | 2024.04.18 |
---|---|
1 실습5 DELETE API todo 삭제 (0) | 2024.04.17 |
1 실습3 POST API todo 생성 (0) | 2024.04.15 |
1 실습2 GET API 단일조회 (0) | 2024.04.09 |
1 실습1 GET API 전체조회 (0) | 2024.04.05 |