기존의 Flask나 Django와는 달리 Fast API는 Type Hints를 사용하고 있다.
Type Hints는 파라미터 값이 어떤 자료형이 들어와야하는 지 코드 상에서 명시하는 것이다.
아래의 예를 보자.
from pydantic import BaseModel
from typing import Optional
class User(BaseModel):
id: int
name = 'Jane Doe'
age : Optional[str] = None
pydantic
의 BaseModel
을 상속받은 User 클래스에 id
필드를 int
형식으로, name
은 Default 값으로 'Jane Doe'
를 주어 type annotation이 불필요하다.
user = User(id='123')
assert user.id == 123 # Valid
여기서 중요한 점은 Pydantic은 Parsing을 도와주는 것일 뿐, Validation Check을 하기 위한 라이브러리는 아니라는 것이다.
좀 더 직관적인 이해를 위한 코드를 보자.
from pydantic import BaseModel
class Model(BaseModel):
a: int
b: float
c: str
print(Model(a=3.1415, b=' 2.72 ', c=123).dict())
#> {'a': 3, 'b': 2.72, 'c': '123'}
print(Model(a=3.1415, **b=' asd '**, c=123).dict())
'''
pydantic.error_wrappers.ValidationError: 1 validation error for Model
b
value is not a valid float (type=type_error.float)
'''
위에서 볼 수 있 듯이, b의 값이 str
으로 들어와도 이를 float
으로 Parsing 해둔다는 것이다. 하지만 만약 Parsing이 불가능한 데이터 형식이 들어왔을 때는 Validation error
를 raise
한다.
데이터 형식을 명시하는 Pydantic은 사용자가 정의한 클래스 또한 annotation을 할 수 있다.
from typing import List
from pydantic import BaseModel
class Foo(BaseModel):
count: int
size: float = None
class Bar(BaseModel):
apple = 'x'
banana = 'y'
class Spam(BaseModel):
foo: **Foo**
bars: **List[Bar]**
m = Spam(foo={'count': 4}, bars=[{'apple': 'x1'}, {'apple': 'x2'}])
print(m)
#> foo=Foo(count=4, size=None) bars=[Bar(apple='x1', banana='y'),
#> Bar(apple='x2', banana='y')]
print(m.dict())
"""
{
'foo': {'count': 4, 'size': None},
'bars': [
{'apple': 'x1', 'banana': 'y'},
{'apple': 'x2', 'banana': 'y'},
],
}
"""
class User(BaseModel):
id: int
name = "John Doe"
signup_ts: Optional[datetime] = None
friends: List[int] = []
external_data = {
"id": "123",
"signup_ts": "2017-06-01 12:22",
"friends": [1, "2", b"3"],
}
user = User(**external_data)
from typing import Set, Tuple
def process_items(items_t: Tuple[int, int, str], items_s: Set[bytes]):
# items_t : int, int, str / 총 3개로 이루어진 튜플
# items_s : byte로 이루어진 set
return items_t, items_s
from typing import Dict
def process_items(prices: Dict[str, float]):
# key는 str, value는 float
for item_name, item_price in prices.items():
print(item_name)
print(item_price)
class Person:
def __init__(self, name: str):
self.name = name
def get_person_name(one_person: Person):
return one_person.name