接上篇:一文掌握异步web框架FastAPI(一)-优快云博客
目录
2)使用json_schema_extra属性(pydantic v2版,旧版是schema_extra)
四、数据校验与错误处理(类型注解和Pydantic)
FastAPI 是一个现代的 web 框架,它利用了 Python 类型提示系统来自动进行数据校验。这意味着如果为 API 路由定义了一个函数,并且指定了参数类型,FastAPI 就会自动校验请求中的数据是否符合这些类型。
此外,FastAPI 可以通过 Pydantic 模型进行数据校验,并自动提供错误响应。Pydantic 是一个用于数据验证的库,它在 FastAPI 中得到了广泛的应用,因为它能够很好地与 FastAPI 的类型检查系统集成。Pydantic 的 BaseModel
类可以用来定义模型,这些模型会被用来解析和验证从 HTTP 请求中获取的数据。
Pydantic 提供了比 FastAPI 内置类型更加丰富的验证功能。例如,它可以自动验证日期格式、邮箱地址等,而不仅仅是基本的类型如 int
, str
。此外,Pydantic 可以处理更复杂的对象关系,比如嵌套对象和列表。
FastAPI 类型注解 如 str
, int
主要用于描述函数参数的预期类型,这有助于 IDEs 和静态分析工具更好地理解代码。但是,对于更复杂的验证逻辑,FastAPI 通常依赖于 Pydantic 或其他第三方库。
下面是一些使用 Pydantic 在 FastAPI 中的例子。
注意:在 FastAPI 中,当使用 Pydantic 模型作为请求体参数时,它会自动将请求体解析为 JSON 格式。这是因为 FastAPI 默认将传入的数据解析为 JSON,并将其映射到指定的 Pydantic 模型。
1、基本的 POST 请求
假设有一个 API 接口需要接收用户的注册信息,可以定义一个模型来描述用户数据:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class User(BaseModel):
username: str
password: str
email: str
@app.post("/users/")
async def create_user(user: User):
# 在这里处理用户数据
return user.dict()
在这个例子中,User
模型定义了注册时需要的三个字段。当一个 POST 请求到达 /users/
时,FastAPI 会尝试将请求体中的 JSON 数据转换成 User
对象。如果转换失败,FastAPI 会返回一个适当的错误响应。
请求脚本:
import requests
# 请求体数据
item_data = {
"username": "username",
"password": "password",
'email': 'example@example.com',
'phone': '1234567890',
}
# 发送 POST 请求
response = requests.post(
url="http://localhost:8000/users/",
json=item_data,
)
if response.status_code == 200:
print("Response:", response.json())
else:
print("Error:", response.status_code, response.text)
2、带有默认值的模型
为模型的字段指定默认值,这样如果客户端没有发送该字段,就会使用默认值:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class User(BaseModel):
username: str
password: str
email: str
phone: str = None
@app.post("/users/")
async def create_user(user: User):
# 在这里处理用户数据
return user.dict()
请求脚本:
import requests
# 请求体数据
item_data = {
"username": "username",
"password": "password",
'email': 'example@example.com',
}
# 发送 POST 请求
response = requests.post(
url="http://localhost:8000/users/",
json=item_data,
)
if response.status_code == 200:
print("Response:", response.json())
else:
print("Error:", response.status_code, response.text)
请求脚本没有传phone,但是回包会返回phone值None
3、复杂的嵌套模型
Pydantic 支持创建嵌套模型,这对于处理复杂的数据结构非常有用
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Address(BaseModel):
street: str
city: str
country: str
class UserProfile(BaseModel):
name: str
address: Address
@app.post("/profiles/")
async def create_profile(profile: UserProfile):
return profile.dict()
请求脚本:
import requests
# 定义要发送的数据
data = {
"name": "张三",
"address": {
"street": "长安街",
"city": "北京",
"country": "中国"
}
}
# 发送 POST 请求
response = requests.post("http://localhost:8000/profiles/", json=data)
# 打印响应内容
print(response.json())
这个例子中,UserProfile
包含了一个 Address
模型作为其属性之一
4、日期时间验证
定义一个Pydantic模型来验证传入的日期时间数据,并创建一个FastAPI路由来接收和处理这些数据。
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, field_validator
from datetime import datetime
# 定义Pydantic模型
class DateTimeModel(BaseModel):
datetime_field: datetime
# 使用Pydantic V2风格的@field_validator
@field_validator('datetime_field')
def datetime_must_not_be_future(cls, v):
if v > datetime.now():
raise ValueError("Date time must not be in the future")
return v
# 创建FastAPI实例
app = FastAPI()
# 创建路由
@app.post("/validate-datetime/")
async def validate_datetime(data: DateTimeModel):
return {"message": "Date time is valid", "received_datetime": data.datetime_field}
# 运行服务器
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="localhost", port=8000)
请求脚本:
import requests
from datetime import datetime
# 定义要发送的日期时间数据
data = {
"datetime_field": datetime.now().isoformat() # 使用当前时间,确保不是未来的时间
}
# 发送POST请求
response = requests.post("http://127.0.0.1:8000/validate-datetime/", json=data)
# 打印响应内容
print(f"Status Code: {response.status_code}")
print(f"Response JSON: {response.json()}")
注意,请求的JSON体应该包含一个符合ISO 8601标准的日期时间字符串,例如:{"datetime_field": "2023-01-01T12:00:00"}
如果要发送一个未来的时间,
可以修改data
字典中的datetime_field
值: