有没有办法在 FastAPI 中手动处理变量验证的异常

Is there a way to manually handle exception from variable validation in FastAPI

嘿,我正在为自己的项目使用 FastAPI,这是我第一次使用它。当我收到的数据与我正在等待的类型不匹配时,我想知道是否有办法让我手动处理异常。

这是一个例子:

async def create_user(password: str = Form("password"), username: str = Form("username"), email: str = Form("email"), pseudo: str = Form("pseudo")):
    conn.execute(user.insert().values(
        username=username,
        email=email,
        password=password,
        pseudo=pseudo
    ))
    return conn.execute(user.select()).fetchall()

我想 return 一个 400 错误和一个个人消息,当这个路由收到一个用户名是一个 int 例如。技术上不应该,但无论如何我想自己处理它,它可能对其他错误处理情况有用。

我还没有在我的研究中找到它,这就是我在这里问的原因。感谢您的帮助!

FastAPI 是使用 Pydantic 构建的,用于此类验证。我可以想到两种方法:

  • (a) 使用 typing.Any 接受任何输入,并在函数中自己验证输入 - 根据需要引发任何 HTTPException

    from typing import Any
    from fastapi import HTTPException
    
    # @app. ....
    async def create_user(password: str = Form("password"), username: Any = Form("username"), email: str = Form("email"), pseudo: str = Form("pseudo")):
    
        if not isinstance(username, str) or (isistance(username, str) and username.isdigit()):
            raise HTTPException(status_code=400, detail="Must be a string.") 
    
        conn.execute(user.insert().values(
            username=username,
            email=email,
            password=password,
            pseudo=pseudo
        ))
        return conn.execute(user.select()).fetchall()
    
  • (b) 将 str 作为默认输入,并检查您要查找的内容。

    from fastapi import HTTPException
    
    # @app. ....
    async def create_user(password: str = Form("password"), username: str = Form("username"), email: str = Form("email"), pseudo: str = Form("pseudo")):
    
        # Assuming you have a proper html form setup in the front-end the expected
        # input to this endpoint will always be a string. If somehow the user sends
        # a request without the form (say with Postman), then Pydantic will be the 
        # one that will catch the error (via 422 error) and not the code below.
        if username.isdigit():
            raise HTTPException(status_code=400, detail="Must be a string.") 
    
        conn.execute(user.insert().values(
            username=username,
            email=email,
            password=password,
            pseudo=pseudo
        ))
        return conn.execute(user.select()).fetchall()
    

无论哪种情况,我认为值得一提的是,FastAPI 的全部意义在于通过 Pyndatic 进行自动验证。如果您计划手动对 一切 进行验证,您最好使用 Starlette 之类的东西,它可以让您更好地控制数据流,但代价是没有内置数据验证器。