FastAPI 기본지식
-- Path Parameter
-- Query Parameter
-- Optional Parameter
-- Request Body
-- Response Body
-- From, File
Pydantic
-- Pydantic
-- Pydantic Validation
-- Pydantic Config
엄청 많이 쓸 내용이니 숙달해보세요 !
Path Parameter한 번 하고 정리하고 ~
웹에서 Get Method를 사용해 데이터를 전송할 수 있음
ID가 402인 사용자 정보를 가져오고 싶은 경우 방식
/users/402
/users?id=402
언제 어떤 방식을 사용해야할까
관련한 자료를 찾아보면 상황마다 다름
/users/{}: Path
/users?name={} : Query
Path Parameter : 저 경로에 존재하는 내용이 없으므로 404 Error발생
Query Parameter : 데이터가 없는 경우 빈 리스트가 나옴 => 추가로 Error Handling필요
Resource를 식별해야 하는 경우: Path Parameter가 더 적합
정렬, 필터링 해야 하는 경우: Query Parameter가 더 적합
Get Method: 정보를 READ하기 위해 사용
유저 정보에 접근하는 API 만들기
FastAPI는 데코레이터로 GET,POST를 표시
@app.get @app.post
Get Method의 인자로 있는 {user_id}가 함수의 값으로 주입
python test_get.py 로 웹서버를 띄우고 localhost:8000/users/1로 접근
터미널에서 Request 로그가 남음
선행학습의 폐해다.
reload=True를 사용하여 간편하게 코드를 수정하고 확인하려 하였으나 예상치못한
You must pass the application as an import string to enable 'reload' or 'workers'.
오류와 만남.
해결방법은 간단했다.
```
uvicorn.run("getMethod:app", host='0.0.0.0', port = 8000, reload=True)
```
예시 : localhost:8000/career/?first=0&limit=1
from typing import Optional
q는 있어도 되고 없어도 됨 !!
내멋대로 만들다가 궁금한거.
@app.get("users/{user_id}")로 선언된 두개의 함수가 있다면?!
그냥 위에꺼가 실행되는걸까?
아무튼 Optional parameter까지 잘실행되는것을 볼 수 있었다.
클라이언트에서 API에 데이터를 보낼 때, Request Body를 사용함
클라이언트=>API: Request Body
API의 Response =>클라이언트: Response Body
Request Body에 데이터가 항상 포함되어야 하는것은 아님
Request Body에 데이터를 보내고 싶다면 POST Method를 사용
참괴 GET Method는 URL, Request Header로 데이터 전달
POST Method는 Request Body에 데이터를 넣어 보냄
Body의 데이터를 설명하는 Content-Type이란 Header필드가 존재하고, 어떤 데이터 타입인지 명시해야함.
대표적인 컨텐츠 타입
-- application/x-www-form-urlencoded : BODY에 Key, Value 사용. &구분자 사용
-- text/plain : 단순 txt파일
-- multipartform-data: 데이터를 바이너리 데이터로 전송
class fullstack(BaseModel):
BaseModel은 pydantic. 후반부에 자세하게 설명. 지금은 그냥 클래스를 만들었구나 알아두기 !
Swagger
Schemas에서 pydantic으로 정의한 내용을 볼 수 있음
빨간 * 이 달려있다면 필수, 아니라면 Optional
POST쪽을 클릭해도 해당 내용 확인할 수 있음
Try it out 클릭
기본 설정 상태에서 Execute누르면 curl명령어, Response가 보임
float에 string을 넣어서 execute하면?!
-- score가 Float이 아니라는 메세지가 출력됨 (validation Check한 것)
API의 Response => 클라이언트: Response Body
Decorator의 response_model 인자로 주입가능
역할
-- Output Data를 해당 정의에 맞게 변형
-- 데이터 Validation
-- Response에 대한 Json Schema 추가
-- 자동으로 문서화
python postMethod.py 웹서버 실행한 후, docs확인
Try it out을 누르고 Execute를 실행
Request 데이터와 Response 데이터가 다름
pip install python-multipart
스승님.. poetry는여???
poetry add python-multipart
프론트도 간단히 만들기 위해 Jinja2 설치 ~~ㅋㅋ이름이 진짜 진자네 ~~
poetry add Jinja2
login_form.html은 Boostcamp model serving에서 가져옴.ㅎㅎ
Method Not Allow Error 5xx
get과 post방식의 차이를 자세히 알아야됨
python postMethod_Form.py를 통해 웹 서버를 실행한후 localhost:8000/login/으로 이동하면
login_form.html을 통해 간단한 login form이 생성됨
제출을 누르면 login 함수가 실행됨(POST 요청)
Form(...): ...는 무엇일까?
Python ellipsis : Required(꼭 필수 요소)를 의미
FastAPI 웹 서버를 실행한 후 Swagger로 이동하면 Required(...)를 볼 수 있음
@app.post('/files/')
def create_f~~
@app.post('/uploadfiles/')
def create_upload_files(~
content = """
<body>
<form action="/files/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
<form action="/uploadfiles/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
</body>
"""
html의 form action="/files/' , form action="/uploadfiles/" 등은
위에서 정의된 @app.post('/files/')와 @app.post('/uploadfiles/')의 함수를 실행한다.
위의 html은 파일업로드와 제출 버튼이 두개씩 존재하게 된다.
Pydantic의 두가지 기능을 알아보자
Validation
-- Machine Learning Model Input Validation
-- Online Serving에서 Input 데이터를 Validation하는 Case
Validation Check Logic
-- 조건 1: 올바른 url을 입력 받음(url)
-- 조건 2: 1-10 사이의 정수 입력 받음(rate)
-- 조건 3: 올바른 폴더 이름을 입력 받음(target_dir)
사용할 수 있는 방법
1 : 일반 Python Class를 활용한 Input Definition 및 Validation
2 : Dataclass를 (python 3.7 이상 필요) 활용한 Input Definition 및 Validation
3 : Pydantic을 활용한 Input Definition 및 Validation
class ModelInput01:
url: str
rate: int
target_dir: str
def __init__(sef,url:str, rate:int, target_dir: str):
self.url = url
self.rate = rate
self.target_dir = target_dir
def validation(self)-> bool:
"""
클래스 필드가 올바른지 검증
Returns:
bool: 검증 성공/실패 여부
"""
validation_results=[self._validate_url(self.url), 1 , self.rate<=10, self._validate_directory(self.target_dir)]
return all(validation_results)
if __name__ == '__main__':
VALID_INPUT ={
'url' : "https://~~~",
'rate': 4,
'target_dir': '/users/~~~'
}
INVALID_INPUT = {
'url': 'wrong_url',
'rate': 11,
'target_dir': 'wrong_dir'
}
valid_python_class_model_input = ModelInput01(**VALID_INPUT)
assert valid_python_class_model_input.validate() is True
invalid_python_class_model_input = ModelInput01(**INVALID_INPUT)
assert invalid_python_class_model_input.validate() is False
의미 없이 길어지는 코드량과 장황한 검증 로직이 눈에 보인다.
사실 pydantic을 접하기 전이라 그런지 아니 뭐.. 이정도면 괜찮지 않나? 싶기도 하다.
dataclass decorator사용으로 init method를 따로 작성할 필요가 없어짐
post init메서드 같은 편의매직메서드 사용 가능
하지만 여전히 validate method를 따로 만들어야함(길어지는 검증 로직을 분리하기 위해)
post init method 사용으로 따로 validate메서드를 호출하지 않아도 생성 시점에서 validation
인스턴스 생성 시점에서 Validation을 수행하기 쉬움
여전히 Validation 로직들을 직접 작성해야 함
Validation 로직을 따로 작성하지 않으면, 런타임에서 type checking을 지원하지 않음
from pydantic import BaseModel, HttpUrl, Field, DirectoryPath
class ModelInput03(BaseModel):
url: HttpUrl
rate: int = Field(ge=1, le=10)
target_dir: DirectoryPath
훨씬 간결해진 코드(6라인)(vs 52라인 Python Class, vs 50라인 data class)
주로 쓰이는 타입들(http url, db url, enum등)에 대한 Validation이 만들어져 있음
런타임에서 Type Hint에 따라서 Validation Error 발생
Custom Type에 대한 Validation도 쉽게 사용 가능
어디서 에러가 발생했는지
location, type, message 등을 알려줌
우리가 알기로 이건 1~1000까지 들어와야되는데 2000이 들어왔다?
저장해둘껀가?버릴껀가?메세지를 날려줄까? 등의 처리가 필요함. 저장해두고 잘못된 데이터가 얼마나 들어오는지
확인해보는것이 좋음
Pydantic은 Config을 체계적으로 관리할 방법을 제공
기존에 다른 라이브러리들은 어떻게 Config를 설정하고 있을까?
애플리케이션은 종종 설정을 상수로 코드에 저장함 ==하드코딩
이것은 Twelve-Factor를 위반
Twelve-Factor는 성정을 코드에서 엄격하게 분리하는 것을 요구함
Twelve-Factor App은 설정을 환경 변수(envvars나 env라고도 불림)에 저장함
환경 변수는 코드 변경 없이 쉽게 배포 때마다 쉽게 변경할 수 있음
코드랑 환경변수는 나눌 수 있다
The Twelve-Factor App이라는 Saas(Software as a Service)를 만들기 위한 방법론을 정리한 규칙들에 따르면, 환경설정은 애플리케이션 코드에서 분리되어 관리되어야 함
.ini, .yaml파일 등으로 config 설정하기
yaml로 환경 설정을 관리할 경우 쉽게 환경을 설정할 수 있지만, 환경에 대한 설정을 코드 하드코딩하는 형태
때문에 변경사항이 생일 때 유연하게 코드를 변경하기 어려움
Flask-style config.py
위의 세 방법 모두 틀린 방법은 아님
실무에서는 무조건 pydantic을 활용하기 보다는, 각 팀에서 맞는 방법을 따라가는 것이 좋음
하지만 실무에서 여러 사람과 협업하는 환경에서 Human Error를 줄여주는 Pydantic의 기능들은 유용!