5

I'm trying to add validation to my route in a fastapi server, followed the instructions here and managed to have added validation on my int path parameters like so:

route1 = router.get("/start={start:int}/end={end:int}")(route1_func)

and my route1_func:

async def route1_func(request: Request,
                      start: int = Path(..., title="my start", ge=1),
                      end: int = Path(..., title="my end", ge=1)):
    if end <= start:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST)
    else:
        return True

and this works great... but i would like to validate the end > start if possible as part of the definition, instead of checking this after going into route1_func

is this possible?

2 Answers 2

4

You can put path params & query params in a Pydantic class, and add the whole class as a function argument with = Depends() after it. The FastAPI docs barely mention this functionality, but it does work.

Then, once you have your args in a Pydantic class, you can easily use Pydantic validators for custom validation.

Here's a rough pass at your use case:

class Route1Request(BaseModel):
    start: int = Query(..., title="my start", ge=1)
    end: int = Query(..., title="my end", ge=1)

    @root_validator
    def verify_start_end(cls, vals: dict) -> dict:
        assert vals.get("end", 0) > vals.get("start", 0)
        return vals

@router.get("/")
async def route1(route1_data: Route1Request = Depends()):
    return True

Note: It wasn't clear to me if you meant to use path params or query params. I wrote this example for Query params, but it can work with Path params with only a few changes.

Sign up to request clarification or add additional context in comments.

3 Comments

When I try this Pydantic throws a ValidationError, but it's not caught by FastAPI and automatically turned into a RequestValidationError, so instead of a nice 422 status code with diagnostics I get a plain Internal Server Error. The solution seems to be explicitly to raise RequestValidationError([ErrorWrapper(ex, ("path"))]) in the validator. Does anyone know if this is the correct approach?
@IanGoldby yes, this is a longstanding problem when using Depends() for query params: github.com/tiangolo/fastapi/issues/1474 It works fine for request bodies. It looks like you're using the recommended workaround. (I haven't needed this myself.)
root_validator has been deprecated
0

You can use your validator function as dependency. The function parameters must be the same as in the path

def check(start: int, end: int):
    print(start, end)
    if start > end:
        raise HTTPException(status_code=400, detail='error message')


@router.get('/{start}/{end}', dependencies=[Depends(check)])
async def start_end(
    start: int,
    end: int
):
    return start, end

1 Comment

Please explain your solution. Code only is not an answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.