目录
嗯,今天的博主讲的挺细
pyCharm自动调整代码格式 ctrl+alt+L
pydantic库
pydantic是一个用来用来执行数据校验的 Python 库。
可以在代码运行时提供类型提示,数据校验失败时提供友好的错误提示
pyCharm中可以安装pydantic插件
基本用法
先引用
from pydantic import BaseModel
定义数据模型
class User(BaseModel):
id: int #必填字段
name: str = "Bob" #有默认值,选填字段
time: Optional[datetime] = None # 时间字段可以不填,不填就是None
friends: List[int] = [] # 列表中的元素要是int类型,或者可以直接转换成int类型
数据实例化
external_data = {
"id": "123",
"time": "2022-2-15 11:42",
"friends":[1,2,"3"]
}
输出
user = User(**external_data) print(user.id, user.friends) # 实例化后调用属性 print(user.dict()) #字典形式 print(user.json()) #json格式
校验失败处理
try: # 这个friend数据类型是int,不能是字符串,有个错误,放在try中
User(id=1, time=datetime.today(), friends=[1, 2, "not number"])
except ValidationError as e:
print(e.json())
递归模型
class Sound(BaseModel):
sound: str
class Dog(BaseModel):
birthday: date
weight: float = Optional[None]
sound: List[Sound] #Dog中嵌套这Sound,递归模型就是指一个嵌套一个
#实例化
dogs = Dog(birthday=date.today(), weight=6.66, sound=[{"sound": "wang wang ~"},{"sound":"ying ying ~"}])
print(dogs.dict())
可选类型 option
from typing import Optional
name: str = "John" #有默认值,选填字段 time: Optional[datetime] = None # 时间字段可以不填,不填就是None
这两种写法实质上一样
FastAPI的请求参数和验证
异步
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional
#实例化应用
app = FastAPI() #这里不一定是app,名字随意
# 数据模型
class CityInfo(BaseModel):
province: str
country: str
is_affected: Optional[bool] = None
# hello_world方法用@app装饰器get方法,这样hello_world方法就变成了接口
@app.get('/')
def hello_world():
return {"hello":"world"}
#异步
@app.put('/city/{city}')
async def city(city: str, city_info: CityInfo):
return {'city':city, 'country': city_info.country, 'is_affected': city_info.is_affected}
交互文档的使用
文档地址127.0.0.1:8000/docs

数据的解析、验证
from fastapi import APIRouter from fastapi import Path # 专门校验路径参数的类 from enum import Enum # 枚举类型 app03 = APIRouter()
1.路径参数和数字验证
# 这个是没有参数
@app03.get('/path/parameters')
def path_params01():
return {"message": "This is a message"}
# 这个有参数,要注意{parameters}和parameters要一致 这两个接口路径一样,一定要注意前后顺序,函数的顺序就是路由的顺序
@app03.get('/path/{parameters}')
def path_params01(parameters: str):
return {"message": parameters}
2.枚举类型验证
class CityName(str, Enum):
Beijing = "Beijing China"
Shanghai = "Shanghai China"
@app03.get('/enum/{city}') # 枚举类型的参数是可供选择的
async def latest(city: CityName):
if city == CityName.Shanghai:
return {"city_name": city, "confired": 1492, "death": 6}
if city == CityName.Beijing:
return {"city_name": city, "confired": 971, "death": 4}
return {"city_name": city, "latest": "unknow"}
3. 文件路径验证
# 通过path parameters传递文件路径
# 因为http://127.0.0.1:8000/chapter03/files/ 这个路径本来就有很多斜杠,如果传递的参数是文件路径的话就容易出错,所以就要加上:path
@app03.get('/files/{file_path:path}')
def filepath(file_path: str):
return f" The file path is {file_path} "
4.关于长度和正则表达式的验证,常用
用到Path类
@app03.get('/path_params/{num}')
# Path类 可以校验,要求num参数是int类型,必填(...),添加标题,添加描述,大于等于1,小于等于10
def path_params_validate( num: int = Path(..., title="your number", description="描述 ", ge=1, le=10) ):
return num
5.查询参数
@app03.get('/query')
# 给了默认值就是选填的参数,没给默认值就是必填参数,也就是这两个都是选填的
def page_limit(page: int=1, limit: Optional[int]=None):
if limit:
return {"page": page, "limit": limit}
return {"page": page}
6.布尔类型转换
# bool类型转换,yes on 1 True true都是true 其他都是false 或者报错
@app03.get('/query/bool/conversion')
def type_conversion(param: bool = False):
return param
7.字符串的验证
@app03.get('/query/validation')
def query_v(
# 查询,必填,最小长度是3,最大长度是16,regex是正则,以a开头
value: str = Query(..., min_length=3, max_length=16, regex="^a"),
# 多个查询参数的列表, default默认值,alias起一个别名
values: List[str] =Query(default=["v1", "v2"], alias="bieming")
):
return value,values
8.请求体和字段
class CityInfo(BaseModel):
name: str = Field(..., example="Beijing") # example是注解的左右,不会被验证
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
}
}
@app03.post("/request_body/city")
def city_info(city: CityInfo):
print(city.name, city.country) #输出到控制台
return city.dict()
9.多参数混合使用
@app03.put('/requeset_body/city/{name}')
def mix_city_info( # 函数
name: str, # 路径参数
city01: CityInfo, # 符合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 city02.dict(), city01.dict()
10.数据格式嵌套的请求体
class Data(BaseModel):
city: List[CityInfo] = None # 这里是定义数据格式嵌套的请求体
date: date #额外的数据类型
confirmed: int = Field(ge=0, description="确诊数", default=0)
death: int = Field(ge=0, description="死亡数", default=0)
recovered: int = Field(ge=0, description="痊愈数", default=0)
@app03.put("/request_body/nested")
def nested(data: Data):
return data
11. cookie参数
@app03.get("/cookie") # 目前效果只能用Postman测试
def cookie(cookie_id: Optional[str] = Cookie(None)): # 定义Cookie参数需要使用Cookie类,否则就是查询参数
return {"cookie_id": cookie_id}
12. Header参数
@app03.get("/header")
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}
这个注释会显示在文档中










