๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Back-end & Server/FastAPI

[FastAPI] ํƒ€์ž… ์ง€์ •, Pydantic

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
๋ฐ˜์‘ํ˜•

'Back-end & Server > FastAPI' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[FastAPI] Form  (0) 2024.02.20
[FastAPI] ๋ชจ๋ธ  (0) 2024.02.20
[FastAPI] ๋งค๊ฐœ๋ณ€์ˆ˜  (0) 2024.02.20
[FastAPI] ๋™์‹œ์„ฑ๊ณผ async / await  (0) 2024.02.19
[FastAPI] ๊ฐœ์š”  (0) 2024.02.19