首页 > 编程问答 >如何检查多个依赖项中是否至少有一个在 Fastapi 中传递

如何检查多个依赖项中是否至少有一个在 Fastapi 中传递

时间:2024-07-30 16:15:54浏览次数:7  
标签:python fastapi

我有一个端点应该适用于两个不同的用户组,如果用户不属于任一组,我想给出正确的错误消息。对于这些组,我创建了也在其他端点中使用的依赖项:

def is_teacher(
    email: str = Depends(get_email),
    db=Depends(get_db)
) -> bool:
    teacher = ...
    if not teacher:
        raise HTTPException(
            status_code=403, detail=f"User {email} is not a teacher"
        )
    return True


def is_principal(
    email: str = Depends(get_email),
    db=Depends(get_db)
) -> bool:
    principal = ...
    if not principal:
        raise HTTPException(
            status_code=403, detail=f"User {email} is not a principal"
        )
    return True

我尝试创建另一个依赖项,例如

def is_teacher_or_principal(
    teacher: bool = Depends(is_teacher),
    principal: bool = Depends(is_principal)
) -> bool:
    if teacher or principal:
        return True
    raise HTTPException(
            status_code=403, detail=f"User {email} is neither principal nor teacher"
        )

但这需要用户既是教师又是校长,因为首先解决了依赖项。

我可以使所有依赖项返回 False 而不是引发异常,但我认为我随后需要在所有端点函数中引发异常,这会导致重复的代码。 我还可以直接在 is_teacher_or_principal 函数中评估教师和校长的价值,但这也感觉像是重复的代码。有没有一种方便的方法来实现依赖项的“OR”运算符,或者我可以以某种方式捕获 is_teacher_or_principal 函数中的 HTTPException 并在那里处理它?


FastAPI 提供了一种更优雅的方式来处理这种情况,而无需引发和捕获异常或复制代码。 可以使用 Security 依赖项和 HTTPAuthorizationCredentials 来实现这一点,结合自定义异常处理。

1. 创建一个自定义异常处理程序:

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials

class NotTeacherOrPrincipal(Exception):
    def __init__(self):
        self.status_code = 403
        self.detail = "User is neither a teacher nor a principal"


app = FastAPI()

@app.exception_handler(NotTeacherOrPrincipal)
async def not_teacher_or_principal_exception_handler(request: Request, exc: NotTeacherOrPrincipal):
    return JSONResponse(status_code=exc.status_code, content={"detail": exc.detail})

2. 修改的依赖项以使用 Security HTTPAuthorizationCredentials

from fastapi import Depends, HTTPException, Security
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer

security = HTTPBearer()

async def is_teacher(
    credentials: HTTPAuthorizationCredentials = Security(security),
    email: str = Depends(get_email),
    db=Depends(get_db)
) -> bool:
    teacher = ...
    if not teacher:
        return False
    return True


async def is_principal(
    credentials: HTTPAuthorizationCredentials = Security(security),
    email: str = Depends(get_email),
    db=Depends(get_db)
) -> bool:
    principal = ...
    if not principal:
        return False
    return True

3. 创建一个检查任一角色的依赖项:

async def is_teacher_or_principal(
    teacher: bool = Depends(is_teacher),
    principal: bool = Depends(is_principal)
):
    if teacher or principal:
        return True
    raise NotTeacherOrPrincipal()

4. 在的端点中使用该依赖项:

@app.get("/some_endpoint", dependencies=[Depends(is_teacher_or_principal)])
async def my_endpoint():
    # 只有当用户是教师或校长时才会执行此操作
    return {"message": "Hello, teacher or principal!"}

解释:

  • 我们使用 Security(security) 依赖项来强制所有需要身份验证的路由。
  • is_teacher is_principal 依赖项现在只返回 True False ,而不是引发异常。
  • is_teacher_or_principal 依赖项检查任一角色是否为真,如果两者都为假,则引发自定义异常 NotTeacherOrPrincipal
  • 自定义异常处理程序捕获 NotTeacherOrPrincipal 异常并返回具有适当状态代码和消息的 JSON 响应。

这种方法有几个优点:

  • 它避免了引发和捕获异常的需要,这在 FastAPI 中可能很昂贵。
  • 它通过将错误处理逻辑移动到一个中心位置来保持代码清洁和可读性。
  • 它允许轻松添加新角色并通过简单地创建新的依赖项来重用现有的角色检查。

总的来说,这种方法提供了一种更简洁、更易于维护且更符合 FastAPI 哲学的方式来处理多个依赖项的授权。

标签:python,fastapi
From: 78810373

相关文章

  • 当 python 极坐标中某些列条目为空时,如何分解 List[_] 列?
    给定如下所示的Polarsdf,如何在两列上调用explode(),同时将空条目扩展到正确的长度以与其行匹配?shape:(3,2)┌───────────┬─────────────────────┐│x┆y││---┆---......
  • 使用python从网站自动下载pdf时出错
    我想从一个名为epadossier.nl的网站自动批量下载pdf我用谷歌搜索了这个并找到了一段代码并修复了一个小错误。所以现在我得到了这个`importrequestsurl="https://www.epadossier.nl/adres/plaats/straat/num"response=requests.get(url)ifresponse.status_cod......
  • 避免字符串连接的嵌套循环的 Pythonic 方法
    我想找到所有5位数字的字符串,其中前三位数字在我的第一个列表中,第二个槽第四个数字在我的第二个列表中,第三到第五个数字在我的最后一个列表中:l0=["123","567","451"]l1=["234","239","881"]l2=["348","551","399"......
  • Python 环境配置(二)安装jupyter、matplotlib、numpy库
    Python环境配置(二)安装jupyter、matplotlib、numpy库一、numpypipinstallnumpy二、matplotlibpipinstallmatplotlib三、jupyter1、anaconda自带Jupyter2、pycharm插件只有Pycharm的Professional版才支持JupyterNotebook,请注意版本3、新建文件#%......
  • 如何使用 PIPE 并行运行 python 子进程?
    我正在使用inkscape将一堆SVG图像转换为PNG。单线程:importsubprocessimporttimeimportosinkscape_path=r'C:\ProgramFiles\Inkscape\bin\inkscape.com'steps=30filenames=[]processes=[]#t_start=time.process_time()t_start=time.time()f......
  • Python sqlite3 删除数据
    要从SQLite表中删除记录,你需要使用DELETEFROM语句。要删除特定的记录,你需要同时使用WHERE子句。要更新特定的记录,你需要同时使用WHERE子句。语法以下是SQLite中DELETE查询的语法- DELETEFROMtable_name[WHEREClause]PythonCopy例子假设我们使用以下查询创建了......
  • Python 环境配置(一)Python、Anaconda、Pycharm的安装
    Python环境配置(一)Python、Anaconda、Pycharm的安装本人之前已安装一次,此次为卸载之后的重新安装。。。一、Python1、下载下载官网:下载链接:DownloadPython|Python.org勾选添加到路径(环境变量)next如图所示之后点close关闭2、验证win+Rcmd:python退出ex......
  • Pycharm 设置 yaml 格式接口测试用例模板 (python+pytest+yaml)
    前言初次编写的伙伴们可能对yaml格式不太熟悉,自己写yaml用例的时候,总是格式对不齐啊记不住设定好的关键字啊等等等琐事是我们可以在pycharm上设置用例模块,通过快捷方式调用出对应的模块,达到高效写用例的目的。 pycharm操作集:1、File-Settings(快捷键Ctrl+Alt+S) 2、Live......
  • Python - Redirecting output of print to a file
    Theprintfunctioncanalsobeusedtowritetoafile.Theoutputofprint,thatisbydefault,senttothescreencanberedirectedtoanopenfile.Forthis,youhavetosupplythefileobjectasanargumentforthenamedparameterfile.Hereisanexa......
  • Python:添加到相对于当前运行脚本的 sys.path 的最佳方法
    我有一个充满脚本的目录(比如说project/bin)。我还有一个位于project/lib的库,并希望脚本自动加载它。这是我通常在每个脚本的顶部使用的:#!/usr/bin/pythonfromos.pathimportdirname,realpath,sep,pardirimportsyssys.path.append(dirname(realpath(_......