FastAPI 解读 by Gascognya

FastAPI 官方文档解读 (二)

2020-09-05  本文已影响0人  Gascognya

Body字段验证

之前我们提到过,QueryPath可以进行字段验证,对长度和取值范围等进行限制。Body中的JSON字段也具有同样的验证,只不过需要声明在Model中,而不是参数中。

class Item(BaseModel):
    name: str
    description: Optional[str] = Field(
        None, title="The description of the item", max_length=300
    )
    price: float = Field(..., gt=0, description="The price must be greater than zero")
    tax: Optional[float] = None

使用Field()可以很好地满足我们的需求。

复杂类型字段的验证

tags: list = []表示普通的列表验证,如果我们想要统一的类型(像数组那样),我们可以使用typingList来表示,例如tags: List[str] = []
你过你要求数据不重复,那么也可以试试set,用typing中的Set来表示tags: Set[str] = set()

model嵌套

class Image(BaseModel):
    url: str
    name: str

class Item(BaseModel):
    name: str
    description: str = None
    price: float
    tax: float = None
    tags: Set[str] = []
    image: Image = None 

使用model作为另一个model中字段的类型也是可以的。并且这也将很常用。

特殊类型验证

pydantic提供了一些定义好的特殊类型,方便对各种内容进行验证。

from pydantic import BaseModel, UrlStr 

class Image(BaseModel):
    url: UrlStr
    name: str

UrlStr便是一种可以验证合法URL的预置类型

列表Body

如果您希望Body中的JSON,最外层是一个列表。那么您需要在参数中像如下一样定义类型。

def create_multiple_images(images: List[Image]):

Dict的Body

除了Model,您也可以使用dict来接收Body。

@app.post("/index-weights/")
async def create_index_weights(weights: Dict[int, float]):
    return weights

这种形式的类型标注,即可用字典来接收。当然JSON不支持int类型的key,不用担心,fastapi会自动转换。

Cookie参数

def read_items(*, ads_id: str = Cookie(None)):像这样声明,即可获取Cookie参数。第一个值为默认值。

Header参数

def read_items(*, user_agent: str = Header(None)):可以接收Header中的参数。如果Header的一个字段具有多个值,可以使用def read_items(x_token: List[str] = Header(None)):这种形式

Response model

关于这部分内容,请看前面关于fastapi源码的解读。

FastAPI 源码阅读 (二) 路由

model之间的转化

pydantic的model提供了.dict()方法,可以将字段导出为字典。这样便实现模型之间的转换。例如:

class UserIn(BaseModel):
    username: str
    password: str
    email: EmailStr

class UserOut(BaseModel):
    username: str
    email: EmailStr

这两个model之间的差别只有password,UserIn的定义需要如下形式

user_in = UserIn(
          username="john", 
          password="secret", 
          email="john.doe@example.com"
)

而UserOut使用dict()导出可能是如下形式

{
    'username': 'john',
    'email': 'john.doe@example.com',
}

我们只需要user_in = UserIn(**user_out.dict(), password="secret")便可达到效果
反过来转换,UserIn的dict中多余的参数,会被UserOut忽略掉。

model的Union

@app.get("/items/{item_id}", response_model=Union[PlaneItem, CarItem]) 
async def read_item(item_id: str):
    return items[item_id]

Union[PlaneItem, CarItem]使得response有更多的选择余地。像response_model=List[Item]也是被允许的

Form表单

= Form(...),该类继承于Body,用法一致。

上一篇下一篇

猜你喜欢

热点阅读