Fastapi. Как отловить исключение валидации базового класса
У меня есть стандартный роутер fastapi в котором я принимаю параметры пагинации через стандартный класс fastapi Params из пакета fastapi_pagination. Делаю я это так:
@router.get('/test', response_model=Page[Foo])
async def get_users(
params: Params = Depends(),
filter: Filter = FilterDepends(Filter),
) -> Any:
pass
Все работает замечательно, но если я из postman передаю size > 100 то у меня вылетает
pydantic_core._pydantic_core.ValidationError: 1 validation error for Params
Это связано, как я думаю, с тем что внутри класса Params есть код:
class Params(BaseModel, AbstractParams):
page: int = Query(1, ge=1, description="Page number")
size: int = Query(50, ge=1, le=100, description="Page size")
def to_raw_params(self) -> RawParams:
return RawParams(
limit=self.size,
offset=self.size * (self.page - 1),
)
Я пробовал уже менять явную типизацию Params на Any, Пробовал сразу устанавливать для этого параметра значения None, или писать свою функцию обработчик, подставляя в Depends(my_func). Максимум чего добился это возвращения ошибки на английском.
Мне бы хотелось как то отлавливать это исключение и оборачивать с свое кастомное исключение. Как можно это сделать?
Ответы (1 шт):
В общем, проще всего было сделать свой кастомный Middleware перехватичк ошибок:
"""Кастомный обработчик ошибок"""
from typing import Any
from fastapi import Request
from pydantic import ValidationError
from starlette import status
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.responses import JSONResponse
class ParamsExceptionHandler(BaseHTTPMiddleware):
"""Кастомный класс для обработки ошибок связанных с валидацией класса Params"""
async def dispatch(self, request: Request, call_next: Any) -> Any:
"""
Обрабатывает исключения, возникающие при валидации параметров классом Params.
Request (Request): Запрос.
Call_next (Any): Следующий обработчик запроса.
Returns (Any): Результат обработки запроса или соответствующий JSONResponse в случае ошибки.
"""
try:
response = await call_next(request)
return response
except ValidationError as e:
if "Params" in repr(e):
return JSONResponse(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
content={"detail": "detail")
return JSONResponse(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
content={"detail": 'Internal Server Error'})
Главное не забыть добавить свой обработчик в middleware вашего приложения fastapi