fastapi之响应模型(下)

105 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第19天,点击查看活动详情

多模型

  • 一个接口很多时候都会涉及多个模型,比如用户注册接口一般会有至少三个模型类:UserInUserOutUserDb
  • 之所以需要这三个模型类是因为:响应用户信息时不应该有密码,密码存DB时也不应该存明文的密码。
 from typing import Union
 ​
 from fastapi import FastAPI
 from pydantic import BaseModel
 ​
 app = FastAPI()
 ​
 ​
 class UserIn(BaseModel):
     username: str
     password: str
     email: str
     full_name: Union[str, None] = None
 ​
 ​
 class UserOut(BaseModel):
     username: str
     email: str
     full_name: Union[str, None] = None
 ​
 ​
 class UserInDB(BaseModel):
     username: str
     hashed_password: str
     email: str
     full_name: Union[str, None] = None
 ​
 ​
 def fake_password_hasher(raw_password: str):
     return "supersecret" + raw_password
 ​
 ​
 def fake_save_user(user_in: UserIn):
     hashed_password = fake_password_hasher(user_in.password)
     user_in_db = UserInDB(**user_in.dict(), hashed_password=hashed_password)
     print("User saved! ..not really")
     return user_in_db
 ​
 ​
 @app.post("/user/", response_model=UserOut)
 async def create_user(user_in: UserIn):
     user_saved = fake_save_user(user_in)
     return user_saved
  • 这个例子中模拟了用户注册接口,接口返回的数据的类型是:UserInDB,但是可以看到使用了response_model=UserOut,这样的话,响应给客户端数据时就会把密码这个字段过滤掉。

Pydantic的.dict()

  • 上面的例子中也可以看到,在创建用户类:UserDb时使用了user_in.dict()
  • 这个dict()是Pydantic类及子类实例化对象的自已绑定方法,用来将对象转化为一个字典。
 UserInDB(**user_in.dict())
  
 # 上面一行代码等价于下面具体实例化,因为user_in.dict() => 一个字典,
 # 然后 **放在一个字典前面就相当于字典中的每个键值对给UserDb当关键字参数了
 ​
 UserInDB(
     username="john",
     password="secret",
     email="john.doe@example.com",
     full_name=None,
 )

简化模型类

  • 上面用户注册接口使用了三个模型类,但是有多个字段重复定义了,我们可以简化它。
  • 通过python中类的继承关系很容易实现。
 from typing import Union
 ​
 from fastapi import FastAPI
 from pydantic import BaseModel
 ​
 app = FastAPI()
 ​
 ​
 class UserBase(BaseModel):
     username: str
     email: str
     full_name: Union[str, None] = None
 ​
 ​
 class UserIn(UserBase):
     password: str
 ​
 ​
 class UserOut(UserBase):
     pass
 ​
 ​
 class UserInDB(UserBase):
     hashed_password: str

响应模型是一个列表

  • 响应模型可以是一个列表,列表中的每个元素都是Pydantic类型的对象
  • 这种一般用在返回相同类型的全部数据,比如所有的商品信息等等。
 from typing import List
 ​
 from fastapi import FastAPI
 from pydantic import BaseModel
 ​
 app = FastAPI()
 ​
 ​
 class Item(BaseModel):
     name: str
     description: str
 ​
 ​
 items = [
     {"name": "Foo", "description": "There comes my hero"},
     {"name": "Red", "description": "It's my aeroplane"},
 ]
 ​
 ​
 @app.get("/items/", response_model=List[Item])
 async def read_items():
     return items

响应模型是普通字典

  • 响应模型可以是普通的包含任意字段的字典
 from typing import Dict
 ​
 from fastapi import FastAPI
 ​
 app = FastAPI()
 ​
 ​
 @app.get("/keyword-weights/", response_model=Dict[str, float])
 async def read_keyword_weights():
     return {"foo": 2.3, "bar": 3.4}