FastAPI 知识点总结 - 第二部分:进阶特性
·
FastAPI 学习总结 - 第二部分:进阶特性
六、数据验证
Pydantic 模型
Pydantic 是 FastAPI 的核心数据验证库,使用 Python 类型提示进行数据验证和序列化。
基本用法:
from pydantic import BaseModel, Field
from typing import Optional, List
class User(BaseModel):
"""用户模型"""
username: str = Field(..., description="用户名", min_length=3, max_length=50)
email: str = Field(..., description="邮箱")
age: int = Field(18, description="年龄", ge=0, le=120)
is_active: bool = Field(True, description="是否活跃")
tags: List[str] = Field([], description="标签列表")
bio: Optional[str] = Field(None, description="个人简介", max_length=500)
Field 参数说明:
| 参数 | 说明 | 示例 |
|---|---|---|
default |
默认值 | Field(18) |
... |
必填字段 | Field(...) |
ge |
大于等于 | Field(..., ge=0) |
gt |
大于 | Field(..., gt=0) |
le |
小于等于 | Field(..., le=100) |
lt |
小于 | Field(..., lt=100) |
min_length |
最小长度 | Field(..., min_length=3) |
max_length |
最大长度 | Field(..., max_length=50) |
pattern |
正则匹配 | Field(..., pattern="^[a-z]+$") |
description |
字段描述 | Field(..., description="用户名") |
自定义验证器
使用 @validator 装饰器添加自定义验证逻辑:
from pydantic import BaseModel, validator
class User(BaseModel):
username: str
email: str
@validator('username')
def username_must_be_alphanumeric(cls, v):
"""验证用户名只能包含字母和数字"""
if not v.isalnum():
raise ValueError('用户名只能包含字母和数字')
return v
@validator('email')
def email_must_contain_at(cls, v):
"""验证邮箱格式"""
if '@' not in v:
raise ValueError('邮箱格式不正确')
return v
查询参数校验
使用 Query 校验查询参数:
from fastapi import Query
@app.get("/search")
def search(
q: str = Query(
None,
description="搜索关键词",
min_length=3,
max_length=50,
regex="^[a-zA-Z0-9]+$"
),
page: int = Query(1, description="页码", ge=1),
page_size: int = Query(10, description="每页数量", ge=1, le=100)
):
"""
搜索接口
:param q: 搜索关键词
:param page: 页码(默认1)
:param page_size: 每页数量(默认10)
:return: 搜索结果
"""
return {
"q": q,
"page": page,
"page_size": page_size,
"results": []
}
路径参数校验
使用 Path 校验路径参数:
from fastapi import Path
@app.get("/items/{item_id}")
def read_item(
item_id: int = Path(
...,
description="商品ID",
gt=0,
le=1000
)
):
"""
获取商品详情
:param item_id: 商品ID(1-1000)
:return: 商品信息
"""
return {"item_id": item_id}
嵌套模型
Pydantic 支持嵌套模型:
from pydantic import BaseModel
from typing import List
class Address(BaseModel):
"""地址模型"""
street: str
city: str
zipcode: str
class User(BaseModel):
"""用户模型"""
username: str
email: str
addresses: List[Address] = [] # 嵌套列表
@app.post("/users")
def create_user(user: User):
return user.dict()
请求示例:
{
"username": "john",
"email": "john@example.com",
"addresses": [
{"street": "123 Main St", "city": "Beijing", "zipcode": "100000"},
{"street": "456 Oak Ave", "city": "Shanghai", "zipcode": "200000"}
]
}
七、异常处理
HTTPException
使用 HTTPException 抛出自定义异常:
from fastapi import HTTPException
# 模拟数据库
items_db = {
1: {"name": "Item 1", "price": 10},
2: {"name": "Item 2", "price": 20}
}
@app.get("/items/{item_id}")
def read_item(item_id: int):
"""
获取商品详情
:param item_id: 商品ID
:return: 商品信息
"""
item = items_db.get(item_id)
if not item:
raise HTTPException(
status_code=404,
detail=f"商品 {item_id} 不存在",
headers={"X-Error": "ItemNotFound"}
)
return item
响应示例(404):
{
"detail": "商品 3 不存在"
}
自定义异常处理器
使用 @app.exception_handler 自定义异常处理:
from fastapi import Request
from fastapi.responses import JSONResponse
# 自定义异常类
class CustomException(Exception):
def __init__(self, status_code: int, message: str):
self.status_code = status_code
self.message = message
# 自定义异常处理器
@app.exception_handler(CustomException)
async def custom_exception_handler(request: Request, exc: CustomException):
return JSONResponse(
status_code=exc.status_code,
content={"error": exc.message}
)
@app.get("/custom-error")
def raise_custom_error():
raise CustomException(
status_code=400,
message="自定义错误信息"
)
全局异常处理器
处理所有未捕获的异常:
from fastapi import Request
from fastapi.responses import JSONResponse
import traceback
@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
"""处理所有未捕获的异常"""
return JSONResponse(
status_code=500,
content={
"error": "服务器内部错误",
"detail": str(exc),
"traceback": traceback.format_exc()
}
)
八、响应处理
响应模型
使用 response_model 指定响应格式:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class UserIn(BaseModel):
"""请求模型"""
username: str
password: str
email: str
class UserOut(BaseModel):
"""响应模型"""
username: str
email: str
@app.post("/users", response_model=UserOut)
def create_user(user: UserIn):
"""
创建用户(不返回密码)
:param user: 用户信息
:return: 用户信息(隐藏密码)
"""
# 实际应用中会保存到数据库
return user
请求示例:
{
"username": "john",
"password": "secret",
"email": "john@example.com"
}
响应示例(密码被过滤):
{
"username": "john",
"email": "john@example.com"
}
响应模型配置
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str = None
price: float
tax: float = 10.5
tags: list = []
items_db = {
"foo": {"name": "Foo", "price": 50.2},
"bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2}
}
@app.get("/items/{item_id}", response_model=Item)
def read_item(item_id: str):
return items_db[item_id]
响应示例(包含默认值):
{
"name": "Foo",
"description": null,
"price": 50.2,
"tax": 10.5,
"tags": []
}
排除未设置的字段
使用 response_model_exclude_unset 只返回实际设置的字段:
@app.get("/items/{item_id}", response_model=Item, response_model_exclude_unset=True)
def read_item(item_id: str):
return items_db[item_id]
响应示例(不包含默认值):
{
"name": "Foo",
"price": 50.2
}
包含/排除特定字段
@app.get("/items/{item_id}", response_model=Item, response_model_include={"name", "price"})
def read_item(item_id: str):
return items_db[item_id]
@app.get("/items/{item_id}", response_model=Item, response_model_exclude={"tax"})
def read_item(item_id: str):
return items_db[item_id]
自定义响应状态码
from fastapi import status
@app.post("/items", status_code=status.HTTP_201_CREATED)
def create_item(name: str):
"""
创建商品(返回201状态码)
:param name: 商品名称
:return: 商品信息
"""
return {"name": name}
自定义响应头
from fastapi import Response
@app.get("/custom-header")
def custom_header(response: Response):
"""
设置自定义响应头
:param response: 响应对象
:return: 消息
"""
response.headers["X-Custom-Header"] = "custom-value"
return {"message": "Hello"}
九、依赖注入
基本依赖
依赖注入允许我们将重复的逻辑抽取为独立的函数:
from fastapi import Depends, FastAPI
app = FastAPI()
def get_db():
"""获取数据库连接"""
db = "数据库连接对象"
print("建立数据库连接")
return db
@app.get("/items")
def read_items(db=Depends(get_db)):
"""
获取商品列表
:param db: 数据库连接(通过依赖注入)
:return: 商品列表
"""
return {"db": db, "items": []}
@app.get("/users")
def read_users(db=Depends(get_db)):
"""
获取用户列表
:param db: 数据库连接(通过依赖注入)
:return: 用户列表
"""
return {"db": db, "users": []}
带 yield 的依赖(资源管理)
使用 yield 实现资源的获取和释放:
from fastapi import Depends
from sqlalchemy.orm import Session
def get_db():
"""
获取数据库会话
使用 yield 确保会话正确关闭
"""
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.get("/items")
def read_items(db: Session = Depends(get_db)):
"""
获取商品列表
:param db: 数据库会话
:return: 商品列表
"""
items = db.query(Item).all()
return items
多级依赖
依赖可以相互依赖:
from fastapi import Depends
def get_config():
"""获取配置"""
return {"secret_key": "secret123"}
def get_db(config=Depends(get_config)):
"""获取数据库连接(依赖配置)"""
db = f"数据库连接使用密钥: {config['secret_key']}"
return db
@app.get("/items")
def read_items(db=Depends(get_db)):
"""
获取商品列表
:param db: 数据库连接
:return: 商品列表
"""
return {"db": db}
带参数的依赖
依赖函数可以接受参数:
from fastapi import Depends, Query
def pagination(
skip: int = Query(0, ge=0),
limit: int = Query(10, ge=1, le=100)
):
"""分页参数依赖"""
return {"skip": skip, "limit": limit}
@app.get("/items")
def read_items(pagination_params=Depends(pagination)):
"""
获取商品列表(分页)
:param pagination_params: 分页参数
:return: 商品列表
"""
items = [{"id": i, "name": f"Item {i}"} for i in range(100)]
skip = pagination_params["skip"]
limit = pagination_params["limit"]
return items[skip : skip + limit]
类作为依赖
使用类作为依赖:
from fastapi import Depends
class Database:
def __init__(self):
self.connection = "数据库连接"
def query(self, sql):
"""执行查询"""
return f"执行SQL: {sql}"
def get_db():
"""获取数据库实例"""
db = Database()
try:
yield db
finally:
# 清理资源
pass
@app.get("/query")
def query_db(db: Database = Depends(get_db)):
"""
查询数据库
:param db: 数据库实例
:return: 查询结果
"""
result = db.query("SELECT * FROM users")
return {"result": result}
全局依赖
为整个应用添加全局依赖:
from fastapi import Depends, FastAPI
app = FastAPI(dependencies=[Depends(get_db)])
@app.get("/items")
def read_items():
"""获取商品列表(自动注入数据库依赖)"""
return {"items": []}
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)