datetime:2022/09/24 15:52
author:nzb
请求参数和验证
from enum import Enum
from typing import Optional, List
from datetime import date
from fastapi import APIRouter, Path, Query, Body, Cookie, Header
from pydantic import Field
from pydantic.main import BaseModel
app3 = APIRouter()
"""Path Parameters and Number Validations 路径参数和数字验证"""
@app3.get("/path/parameters")
async def path_params01():
return {"message": "This is message"}
@app3.get("/path/{parameters}") # 函数的顺序就是路由的顺序
async def path_params02(parameters: str):
return {"message": parameters}
class CityName(str, Enum):
BeiJing = "BeiJing China"
Shanghai = "Shanghai China"
@app3.get("/enum/{city}") # 枚举类型的参数
async def latest(city: CityName):
if city == CityName.BeiJing:
return {"city_name": city, "confirmed": 1492, "death": 7}
elif city == CityName.Shanghai:
return {"city_name": city, "confirmed": 971, "death": 9}
return {"city_name": city, "latest": "unknown"}
@app3.get("/files/{file_path:path}") # 通过path parameters传递文件路径
async def filepath(file_path: str):
return f"The file path is {file_path}"
@app3.get("/validate_path/{num}")
async def path_params_validate(
num: int = Path(..., title="Your Number", description="不可描述", ge=1, le=10)
):
return num
"""Query Parameters and String Validations 查询参数和字符串验证"""
@app3.get("/query")
async def page_limit(page: int = 1, limit: Optional[int] = None):
if limit:
return {"page": page, "limit": limit}
return {"page": page}
@app3.get("/query/bool/conversion")
async def type_conversion(param: bool = True):
return param
@app3.get("/query/validations") # 长度+正则表达式验证,比如长度8-16位,以a开头。其它校验方法看Query类的源码
async def query_params_validate(
value: str = Query(..., min_length=5, max_length=10, regex="^a"), # ...换成None就变成选填的参数
values: List[str] = Query(["v1", "v2"], alias="alias_name") # 多个查询参数的列表。参数别名
):
return value, values
"""Request Body and Fields 请求体和字段"""
class CityInfo(BaseModel):
name: str = Field(..., example="Beijing")
country: str
country_code: str = None
country_population: int = Field(default=800, title="人口数量", description="国家人口数量", ge=800)
class Config:
schema_extra = {
"example": {
"name": "Shanghai",
"country": "China",
"country_code": "CN",
"country_population": 1400000000
}
}
@app3.post("/request_body/city")
async def city_info(city: CityInfo):
print(city.name, city.country)
return city.dict()
"""Request Body + Path parameters + Query parameters 多参数混合"""
@app3.put("/request_body/city/{name}")
async def mix_city_info(
name: str,
city01: CityInfo,
city02: CityInfo, # Body可以是多个的
confirmed: int = Query(ge=0, description="确诊数", default=0),
death: int = Query(ge=0, description="死亡数", default=0)
):
if name == "Shanghai":
return {"Shanghai": {"confirmed": confirmed, "death": death}}
return city01.dict(), city02.dict()
@app3.put("/request_body/multiple/parameters")
async def body_multiple_parameters(
city: CityInfo = Body(..., embed=True), # 当只有一个Body参数的时候,embed=True表示请求体参数嵌套。多个Body参数默认就是嵌套的
confirmed: int = Query(ge=0, description="确诊数", default=0),
death: int = Query(ge=0, description="死亡数", default=0)
):
print(f"{city.name} 确诊数:{confirmed} 死亡数:{death}")
return city.dict()
"""Request Body - Nested Models 数据格式嵌套的请求体"""
class Data(BaseModel):
city: List[CityInfo] = None
date: date
confirmed: int = Field(ge=0, description="确诊数", default=0)
deaths: int = Field(ge=0, description="死亡数", default=0)
recovered: int = Field(ge=0, description="痊愈数", default=0)
@app3.put("/request_body/nested")
async def nested_models(data: Data):
return data
"""Cookie 和 Header 参数"""
@app3.get("/cookie") # 效果只能用Postman测试
async def cookie(cookie_id: Optional[str] = Cookie(None)):
return {"cookie_id": cookie_id}
@app3.get("/header")
async def header(user_agent: Optional[str] = Header(None, convert_underscores=True), x_token: List[str] = Header(None)):
"""
有些HTTP代理和服务器是不允许在请求头中带有下划线的,所以Header提供convert_underscores属性让设置
:param user_agent: convert_underscores=True 会把 user_agent 变成 user-agent
:param x_token: x_token是包含多个值的列表
:return:
"""
return {"User-Agent": user_agent, "x_token": x_token}