如何在装饰器中获取请求对象而不在路由中显式指定它?我已经有很多路由器了,我不想把
request: Request
放入每个路由器中。
工作原理:
def decorator_func(...):
def decorator(func):
@wraps(func)
async def wrapper(request, *args, **kwargs):
return await func(args, kwargs)
return wrapper
return decorator
@router.get(path='/something')
@decorator_func(...)
def get_something(request: Request):
...
我想要什么:
def decorator_func(...):
def decorator(func):
@wraps(func)
async def wrapper(*args, **kwargs):
request = ... # GET request object
return await func(args, kwargs)
return wrapper
return decorator
@router.get(path='/something')
@decorator_func(...)
def get_something(...):
...
您可以使用路由装饰器的
dependencies
参数来调用特定的依赖项作为请求流的一部分,特别是当您不打算使用它们的返回值时。
通过在依赖项中使用
yield
,您可以在调用控制器之前和之后运行代码:
from fastapi import Depends, FastAPI, Request
app = FastAPI()
def conditional_dependency(request: Request):
print(f"I'm before request {request}")
yield
print(f"I'm after request {request}")
@app.get(path='/something', dependencies=[Depends(conditional_dependency)])
def get_something():
print("This is the request itself")
这会导致输出:
I'm before request <starlette.requests.Request object at 0x0000021686F75240>
This is the request itself
I'm after request <starlette.requests.Request object at 0x0000021686F75240>
调用端点时。
当您想要将特定功能应用于整个路由器(而不是应用程序中的其他路由器)时,这也很有用:
from fastapi import APIRouter, Depends, FastAPI, Request
app = FastAPI()
def conditional_dependency(request: Request):
print(f"I'm before request {request}")
yield
print(f"I'm after request {request}")
router_with_dependency = APIRouter(
dependencies=[Depends(conditional_dependency)]
)
app.mount('/foo', router_with_dependency)
@router_with_dependency.get(path='/something')
def get_something():
print("This is the request itself")
向
/foo/something
发出请求将为在该路由器上注册的每个端点运行依赖项,而在应用程序对象或其他路由器上注册的端点不会自动调用它。
扩展 Mats 的答案,如果您想要传递的数据是常量,您可以将装饰器包装在工厂函数中,然后您同时拥有请求和数据:
def dep_with_data(data: str):
def conditional_dependency(request: Request):
print(f"I'm before request {request}, data is {data}")
yield
print(f"I'm after request {request}, data is {data}")
return conditional_dependency
@app.get(path='/something', dependencies=[Depends(dep_with_data("something"))])
def get_something():
print("This is the request itself")
@app.get(path='/another', dependencies=[Depends(dep_with_data("another thing"))])
def get_another():
print("This is the request itself")
如果这是您需要传递的唯一依赖项,您可以将更多内容移动到包装器以缩短每次使用它时的代码:
def dep_with_data(data: str):
def conditional_dependency(request: Request):
print(f"I'm before request {request}, data is {data}")
yield
print(f"I'm after request {request}, data is {data}")
return {
"dependencies": [Depends(conditional_dependency)]
}
@app.get(path='/something', **dep_with_data("something"))
def get_something():
print("This is the request itself")
@app.get(path='/another', **dep_with_data("another thing"))
def get_another():
print("This is the request itself")