文章目录
- 1. response_model
- 2. 添加输出模型
- 3. 响应模型编码参数
- 4. response_model_include 和 response_model_exclude
- 5. 代码复用:继承
- 6. Union
- 7. 任意 dict 的响应
- 8. 响应状态码
- 9. 表单参数
learn from https://fastapi.tiangolo.com/zh/tutorial/response-model/
1. response_model
响应模型 不是 路径参数
from typing import Optional, List
from fastapi import Cookie, FastAPI, Header
from pydantic import BaseModelapp = FastAPI()class Item(BaseModel):name: strdescription: Optional[str] = Noneprice: floattax: Optional[float] = Nonetags: List[str] = []@app.post("/items/", response_model=Item) # 装饰器方法的一个参数
async def create_items(item: Item):return item
or
@app.post("/items/", response_model=List[Item]) # 装饰器方法的一个参数
async def create_items(item: Item):return [item, item]
响应模型 对 返回的数据 进行转换,校验
例如:
from typing import Optional, List
from fastapi import Cookie, FastAPI, Header
from pydantic import BaseModel, EmailStrapp = FastAPI()class UserIn(BaseModel):username: strpassword: stremail: EmailStrfull_name: Optional[str] = None@app.post("/user/", response_model=UserIn) # 装饰器方法的一个参数
async def create_user(user: UserIn):return user
永远不要 存储用户的 明文密码,也不要在响应中 发送密码。
2. 添加输出模型
- 输出的时候不给密码,更改响应模型为不带密码的
from typing import Optional, List
from fastapi import Cookie, FastAPI, Header
from pydantic import BaseModel, EmailStrapp = FastAPI()class UserIn(BaseModel):username: strpassword: stremail: EmailStrfull_name: Optional[str] = Noneclass UserOut(BaseModel):username: stremail: EmailStrfull_name: Optional[str] = None@app.post("/user/", response_model=UserOut) # 装饰器方法的一个参数
async def create_user(user: UserIn):return user
3. 响应模型编码参数
response_model_exclude_unset
参数 True,输出忽略 未明确设置的 字段response_model_exclude_defaults=True
,忽略跟默认值一样的字段response_model_exclude_none=True
,忽略 None 的字段
from typing import Optional, List
from fastapi import Cookie, FastAPI, Header
from pydantic import BaseModel, EmailStrapp = FastAPI()class Item(BaseModel):name: strdescription: Optional[str] = Noneprice: floattax: float = 10.5tags: List[str] = []items = {"foo": {"name": "Foo", "price": 50.2},"bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},"baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}@app.get("/items/{item_id}", response_model=Item, response_model_exclude_unset=True)
async def read_item(item_id: str):return items[item_id]
如果参数 改为 False,或者 删除该参数,未设置的值 也显示出来了
4. response_model_include 和 response_model_exclude
它们接收一个由属性名称 str 组成的 set 来包含(忽略其他的)或者排除(包含其他的)这些属性
response_model_include
, 只包含指定字段response_model_exclude
,排除指定字段
from typing import Optional, List
from fastapi import Cookie, FastAPI, Header
from pydantic import BaseModel, EmailStrapp = FastAPI()class Item(BaseModel):name: strdescription: Optional[str] = Noneprice: floattax: float = 10.5items = {"foo": {"name": "Foo", "price": 50.2},"bar": {"name": "Bar", "description": "The Bar fighters", "price": 62, "tax": 20.2},"baz": {"name": "Baz","description": "There goes my baz","price": 50.2,"tax": 10.5,},
}@app.get("/items/{item_id}/name",response_model=Item,response_model_include={"name", "description"}, # { } 表示 set, 使用 [ ] 也可以
)
async def read_item_name(item_id: str):return items[item_id]@app.get("/items/{item_id}/public", response_model=Item, response_model_exclude={"tax"})
async def read_item_public_data(item_id: str):return items[item_id]
5. 代码复用:继承
from typing import Optional
from fastapi import FastAPI
from pydantic import EmailStr, BaseModel
app = FastAPI()class UserIn(BaseModel):username: strpassword: stremail: EmailStrfull_name: Optional[str] = Noneclass UserOut(BaseModel):username: stremail: EmailStrfull_name: Optional[str] = Noneclass UserInDB(BaseModel):username: strhashed_password: stremail: EmailStrfull_name: Optional[str] = Nonedef fake_password_hasher(raw_password: str):return "supersecret" + raw_passworddef 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)# 使用user_in的数据初始化UserInDB , 并添加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
- 通过继承进行复用
from typing import Optional
from fastapi import FastAPI
from pydantic import EmailStr, BaseModel
app = FastAPI()class UserBase(BaseModel):username: stremail: EmailStrfull_name: Optional[str] = Noneclass UserIn(UserBase):password: strclass UserOut(UserBase):passclass UserInDB(UserBase):hashed_password: strdef fake_password_hasher(raw_password: str):return "supersecret" + raw_passworddef 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)# 使用user_in的数据初始化UserInDB , 并添加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
6. Union
- 响应将是 多种类型中的 任何一种
from typing import Optional, Union
class BaseItem(BaseModel):description: strtype: strclass CarItem(BaseItem):type = "car"class PlaneItem(BaseItem):type = "plane"size: intitems = {"item1": {"description": "All my friends drive a low rider", "type": "car"},"item2": {"description": "Music is my aeroplane, it's my aeroplane","type": "plane","size": 5,},
}@app.get("/items/{item_id}", response_model=Union[PlaneItem, CarItem])
async def read_item(item_id: str):return items[item_id]
7. 任意 dict 的响应
- 对于事先不知道 key 的,可以直接定义字典及其 k, v 的类型
@app.get("/keyword-weights/", response_model=Dict[str, float])
async def read_keyword_weights():return {"foo": 2.3, "bar": 3.4}
8. 响应状态码
- 装饰器函数内 使用
status_code
参数来声明用于响应的HTTP 状态码
@app.get("/items/{item_id}", response_model=Union[PlaneItem, CarItem],status_code=208)
async def read_item(item_id: str):return items[item_id]
关于 HTTP 状态码
在 HTTP 协议中,你将发送 3 位数的数字状态码作为响应的一部分。
-
100
及以上状态码用于「消息」响应。你很少直接使用它们。具有这些状态代码的响应不能带有响应体。 -
200
及以上状态码用于「成功」响应。这些是你最常使用的。200
是默认状态代码,它表示一切「正常」。- 另一个例子会是
201
,「已创建」。它通常在数据库中创建了一条新记录后使用。 - 一个特殊的例子是
204
,「无内容」。此响应在没有内容返回给客户端时使用,因此该响应不能包含响应体。
-
300
及以上状态码用于「重定向」。具有这些状态码的响应可能有或者可能没有响应体,但304
「未修改」是个例外,该响应不得含有响应体。 -
400
及以上状态码用于「客户端错误」响应。这些可能是你第二常使用的类型。- 一个例子是
404
,用于「未找到」响应。 - 对于来自客户端的一般错误,你可以只使用
400
。
- 一个例子是
-
500
及以上状态码用于服务器端错误。你几乎永远不会直接使用它们。当你的应用程序代码或服务器中的某些部分出现问题时,它将自动返回这些状态代码之一。
from fastapi import FastAPI, status
status_code=status.HTTP_201_CREATED # 可以使用代码补全,不必记住
9. 表单参数
- 接收的不是 JSON,而是表单字段时,要使用 Form
from fastapi import FastAPI, Form
app = FastAPI()@app.post("/login/")
async def login(username: str = Form(...),password: str = Form(...)):return {"username" : username}