Louis FELDMAR
Louis FELDMAR

Reputation: 9

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

Hey I'm using FastAPI for a project of my own and it's my first time using it. I wonder if there is a way for me to manually handle the exception when the data I'm receiving does not match the type I'm waiting for.

Here's an example :

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()

I would like to return a 400 error and a personnal message when this route receive a username that is an int for example. Technically not supposed to but I want to handle it myself anyway, it could be usefull for other error handling situations.

I haven't found it on my research yet and that's why I'm asking here. Thanks for help !

Upvotes: 0

Views: 727

Answers (1)

felipe
felipe

Reputation: 8055

FastAPI is built with Pydantic for these sort of validations. There are two ways I can think of doing this:

  • (a) Use typing.Any to accept any input, and validate the input yourself in the function- raising any HTTPException as needed.

    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) Take in a str input as the default, and check for the things you are looking for.

    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()
    

Whichever the case, I think it's worth mentioning that the entire point of FastAPI is for automatic validation via Pyndatic. If you plan on doing validation manually for everything, you are better off working with something like Starlette, which gives you more control of the flow of data at the cost of not having built-in data validators.

Upvotes: 1

Related Questions