FastAPI中如何在依赖项与端点函数间共享相同参数
问题根因
当前代码重复触发校验的核心原因是:SomeModel被独立声明为两次参数解析目标,一次是端点函数的data入参,一次是依赖函数dependency_function的入参。FastAPI默认会为每个独立声明的请求参数单独走完解析、Pydantic校验全流程,因此校验逻辑会被执行两次,才会出现重复抛出ValidationError的现象。
另外原代码存在两处隐藏问题:一是实例化的FastAPI应用对象为application,但路由装饰器使用了未定义的router对象,运行时会直接抛错;二是Pydantic校验器方法在校验通过时未返回原值,会导致解析后的some_value字段为None。
修复方案
利用FastAPI 同请求域依赖缓存特性修复:同一请求生命周期内,完全相同的依赖项只会被执行一次,后续所有引用位置直接读取第一次执行的缓存结果,不会重复触发解析校验逻辑。
该方案不需要依赖返回字典,端点和其他依赖都可以直接拿到原生Pydantic模型实例,符合常规使用习惯,修正后可运行代码如下:
import fastapi from pydantic import BaseModel, validator application = fastapi.FastAPI() # 若使用APIRouter拆分路由,提前实例化router替换下方的application即可,逻辑完全一致 class SomeModel(BaseModel): some_value: str @validator('some_value') def validate_some_value(value: str) -> str: if value == 'swearing': raise ValueError('The given value is invalid.') return value # 抽离公共的请求体解析依赖,作为共享模型实例的统一入口 def get_validated_request_body(data: SomeModel) -> SomeModel: return data def dependency_function(data: SomeModel = fastapi.Depends(get_validated_request_body)) -> bool: match data.some_value: case 'Hello': return True case 'World': print('Hello, World!') return False default: return False @application.post('/some-endpoint') async def send_value( data: SomeModel = fastapi.Depends(get_validated_request_body), data_is_valid: bool = fastapi.Depends(dependency_function) ): if data_is_valid: # 替换为实际的邮件发送逻辑 print(f"Send message to admin@gmail.com, content: {data.some_value}")
方案说明
- 整个请求处理流程中,
get_validated_request_body仅会执行一次,SomeModel的Pydantic校验逻辑仅运行一遍,不会出现重复抛错的问题 - 端点函数、任意层级的依赖项只要声明
data: SomeModel = fastapi.Depends(get_validated_request_body),就能拿到同一份已经校验完成的模型实例,不需要做字典拆包等额外操作 - 该方案对查询参数、路径参数、请求头、Cookie等所有FastAPI支持的参数类型复用都生效,没有场景限制
内容的提问来源于stack exchange,提问作者Michael Aboryone
相关产品推荐
相关产品推荐

