首页 > 解决方案 > 如何将自定义装饰器添加到 FastAPI 路由?

问题描述

我想为auth_required我的端点添加一个装饰器。(请考虑这个问题是关于装饰器,而不是中间件

所以一个简单的装饰器看起来像这样:

def auth_required(func):
    def wrapper(*args, **kwargs):
        if user_ctx.get() is None:
            raise HTTPException(...)
        return func(*args, **kwargs)
    return wrapper

所以有两种用法:

@auth_required
@router.post(...)

或者

@router.post(...)
@auth_required

第一种方法不起作用,因为router.post创建了一个保存到self.routesAPIRouter 对象中的路由器。第二种方法不起作用,因为它无法验证 pydantic 对象。对于任何请求模型,它都说missing args, missing kwargs.

所以我的问题是 - 如何将任何装饰器添加到 FastAPI 端点?我应该进入router.routes并修改现有端点吗?或者使用一些functools.wraps类似的功能?

标签: pythonpython-decoratorsfastapipydantic

解决方案


如何将任何装饰器添加到 FastAPI 端点?

正如你所说,你需要使用@functools.wraps(...)--(PyDoc)装饰器,

from functools import wraps

from fastapi import FastAPI
from pydantic import BaseModel


class SampleModel(BaseModel):
    name: str
    age: int


app = FastAPI()


def auth_required(func):
    @wraps(func)
    async def wrapper(*args, **kwargs):
        return await func(*args, **kwargs)

    return wrapper


@app.post("/")
@auth_required # Custom decorator
async def root(payload: SampleModel):
    return {"message": "Hello World", "payload": payload}

此方法的主要警告是您无法访问request包装器中的对象,我认为这是您的主要意图。

如果您需要访问请求,则必须将参数添加到路由器函数中,

from fastapi import Request


@app.post("/")
@auth_required  # Custom decorator
async def root(request: Request, payload: SampleModel):
    return {"message": "Hello World", "payload": payload}

我不确定FastAPI中间件有什么问题,毕竟@app.middleware(...)也是一个装饰器。


推荐阅读