使用fastapi-cache时如何同时获取FastAPI请求状态与请求体参数
我有一个FastAPI POST接口,接收请求体中的参数,全局通过FastAPI的Depends设置了Request状态值,需要在接口方法中获取该值。
以下代码运行正常:
from pydantic import BaseModel from fastapi import APIRouter, Request class MyPydanticValue(BaseModel): # some properties here router = APIRouter() @router.post("/foo") def perform_action( my_val: MyPydanticValue, request: Request ): # do something with my_val ... # and also reference a state value that was set globally elsewhere print(request.state.x_some_value)
FastAPI会自动识别my_val为Pydantic模型并从请求体解析数据。
但添加fastapi-cache的@cache装饰器后出现异常:
@router.post("/foo") @cache(expire=300) def perform_action( my_val: MyPydanticValue, request: Request ): # do something with my_val ... #and also reference a state value that was set globally elsewhere print(request.state.x_some_value)
异常信息:
TypeError: perform_action() got multiple values for argument 'my_val'
根据fastapi-cache文档说明:
The cache decorator injects dependencies for the Request and Response objects, so that it can add cache control headers to the outgoing response, and return a 304 Not Modified response when the incoming request has a matching If-Non-Match header. This only happens if the decorated endpoint doesn't already list these dependencies already.
我本以为自己已经声明了Request参数,缓存装饰器就不会再注入该依赖,但查看源码后发现,fastapi-cache和FastAPI都注入了request参数,导致参数冲突。
想知道哪里操作有误?有没有解决方法?如何在接口函数中同时获取请求状态值并解析请求体中的Pydantic模型?
方法1:通过Depends声明Request参数
将直接声明的request: Request改为通过Depends()注入,这样fastapi-cache能正确识别你已声明该依赖,不会重复注入:
from fastapi import Depends, Request @router.post("/foo") @cache(expire=300) def perform_action( my_val: MyPydanticValue, request: Request = Depends() ): # 业务逻辑 print(request.state.x_some_value)
方法2:关闭装饰器的自动注入(版本兼容)
若你使用的fastapi-cache版本支持,可通过inject_request_response=False参数关闭装饰器自动注入Request/Response的逻辑,避免冲突:
@cache(expire=300, inject_request_response=False)
注意:该参数需确认是否存在于你使用的v0.2.1版本中,若不存在则优先使用方法1。
原理说明
fastapi-cache的装饰器对直接声明的Request参数检测逻辑存在缺陷,无法正确识别已声明的依赖,而通过Depends()声明的依赖能被装饰器正确检测到,从而避免重复注入,解决参数冲突问题。
内容的提问来源于stack exchange,提问作者John

