[FastAPI] νμ μ§μ , Pydantic
π° FastAPI 곡μλ¬Έμλ₯Ό 보면μ κ°μΈμ μΌλ‘ μ 리ν κΈ μ
λλ€.
Type
FastAPIλ νμ΄μ¬μ Type Annotationμ κΈ°λ°μ λκ³ μλ€.
μ΄λ₯Ό ν΅ν΄ νμ΄μ¬ λ³μλ₯Ό μ μΈνκ±°λ ν¨μμ κ°μ 리ν΄ν λ νμ μ μ§μ ν μ μλ€.
μ΄λ¬ν Type Annotationμ ":"μ μ¬μ©νμ¬ λͺ μν μ μλ€.
(λ°ν νμ μ "->" λ‘ μ§μ )
Simple Type
- int
- float
- str
- bool λ±μ νμ΄μ¬ νμ€νμ
def getItem(a:int,b:float)->int:
return a+int(b)
result:int = getItem(1,1.5)
print(result)
νμ λ§€κ°λ³μλ₯Ό νμ©ν Generic(μ λ€λ¦) νμ
- list, dict, set, tuple κ°μ κ°μ μ μ₯ν μ μλ λ°μ΄ν° ꡬ쑰μ λ΄λΆλ κ°μμ νμ μ κ°μ§ μ μλ€.
- typingμ μ΄μ©ν΄ λ΄λΆ Type Annotationμ μ§μ ν μ μλ€. (List, Dict, Set, Tuple)
from typing import List
def getItems(items: List[str]) -> None:
for item in items:
print(item)
getItems(["1", "2", "3", "4"])
from typing import Set, Tuple, Dict
def getItems1(it1: Tuple[int, int, float], it2: Set[int]) -> None:
for item in zip(it1, it2):
print(item)
def getItems2(dic: Dict[str, int]) -> None:
for k, v in dic.items():
print(k, v)
getItems1((1, 2, 1.0), {1, 2, 3})
getItems2({"h": 1, "b": 3, "e": 2})
Optional νμ μ μ¬μ©ν΄μ "μ νμ "μΌλ‘ νμ μ μ§μ ν μ μλ€.
from typing import Optional
def getItems(items: Optional[int] = None) -> None:
# νμ intκ° μλλΌ Noneμ΄ λ μλ μμ
for item in items:
print(item)
getItems([1, 2, 3, None])
Union[X,Y] νμ μΌλ‘ X λλ Y νμ μ μ§μ ν μ μλ€.
from typing import Union
def getItems(items: list) -> Union[int, list]:
return items[:2]
d: Union[int, list] = None
d = getItems([1, 2, 3, 4])
print(d)
Pydantic
λ°μ΄ν° κ²μ¦(Validation)μ μν λΌμ΄λΈλ¬λ¦¬μ΄λ€.
- ex) 볡μ‘ν μλΉμ€ λ‘μ§μμ κ°λ°μκ° μνλ λ°©ν₯μΌλ‘ νλ₯΄κ² λ§λ€μ΄μΌ νλ, μ¬μ©μλ€μ μλͺ»λ μ λ ₯μΌλ‘ μΈν λ¬Έμ λ₯Ό λ°©μ§νκΈ° μν΄ νΉμ μ νκ³Ό μ μ½μ‘°κ±΄μ ν΅ν΄ λ°μ΄ν° κ²μ¦μ νλ€.
νμ μ μ μ½μ‘°κ±΄ 보μ₯κ³Ό μΆλ ₯ λͺ¨λΈμ μ νκ³Ό μ μ½μ‘°κ±΄μ 보μ₯νλ€.
FastAPIμμ API νΈμΆ μ μΆλ ₯ λͺ¨λΈμ μ νκ³Ό μ μ½μ‘°κ±΄μ 보μ₯μν€κΈ° μν΄ μ¬μ©νλ€ μκ°νλ©΄ λλ€.
pip install pydantic
from pydantic import BaseModel
from typing import Union
class Item(BaseModel):
name: str
desc: Union[str, None] = None
price: float
tax: Union[float, None] = None
if __name__ == "__main__":
data = {
'name': 'toy',
'desc': 'μ₯λκ°',
'price': 4.7,
'tax': 0.2
}
toy = Item(**data)
print(toy)
print()
data = {
'name': 'toy',
'desc': 'μ₯λκ°',
'price': 'dd',
'tax': 0.2
}
toy = Item(**data)
print(toy)
νμ μ λ§μ§ μμ κ°μ μ λ¬μ μλ¬ λ°μ
π₯ μ μλμ§ μμ κ°μ΄ λ€μ΄κ°κ±°λ λ³ν κ°λ₯ν κ²½μ° μ μλ νλμ λ§λλ‘ μ²λ¦¬ν΄μ€.
Constrained typesμ μ¬μ©ν΄ μμ μ μ νμ μ μ©ν μ μλ€.
from pydantic import BaseModel, constr, conint
class Person(BaseModel):
f_name: str
# 3 <= λ¬Έμμ΄ κΈΈμ΄ <= 4
l_name: constr(min_length=3, max_length=4)
# 1 <= κ° <= 25
age: conint(ge=1, le=25)
if __name__ == "__main__":
data = {
'f_name': "Pupba",
'l_name': "Jung",
'age': 25
}
p = Person(**data)
print(p)
Validator decoratorλ₯Ό μ¬μ©ν΄μ μ체μ μΈ κ·μΉμ λ§λ€μ΄ λ°μ΄ν° κ²μ¬λ₯Ό ν μ μλ€.
from pydantic import BaseModel, validator, ValidationError
from typing import Union
class Person(BaseModel):
name: str
age: int
# μ΄λ¦ κ²μ¬
@validator('name')
def name_must_english(cls, v):
assert v.encode().isalpha(), ValidationError('Name Must be english')
return v
# λμ΄ κ²μ¬
@validator('age')
def is_adult(cls, v):
if v <= 19:
raise ValidationError('μ μ‘μ΄ κ΅¬λ§')
return v
if __name__ == "__main__":
data = {
'name': "pupba",
'age': 15
}
try:
pupba = Person(**data)
print(pupba)
except ValidationError as e:
print(e)
Modelλ‘λΆν° JSONμ λ§λλ κ²λ κ°λ₯νλ€.
from pydantic import BaseModel
class Person(BaseModel):
f_name: str
l_name: str
age: int
if __name__ == "__main__":
data = {
'f_name': "Pupba",
'l_name': "Jung",
'age': 25
}
json = Person(**data).model_dump_json()
print(json)
μμ±λ λͺ¨λΈμ model_dump_json()λ‘ JSONμΌλ‘ λ³νν μ μλ€.