Back-end & Server/FastAPI

[FastAPI] νƒ€μž… μ§€μ •, Pydantic

Pupbani 2024. 2. 19. 21:22
728x90
λ°˜μ‘ν˜•

 

🐰 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으둜 λ³€ν™˜ν•  수 μžˆλ‹€.

 

 

728x90
λ°˜μ‘ν˜•