Как изменить ответ при ошибке валидации от pydantic в FastAPI
Есть такая схема:
CONST_DATA = ['a', 'b']
class Sample(BaseModel):
field1: str
field2: str
@validator("field2")
def validate_fied2(cls, value):
if value in CONST_DATA:
return value
raise PydanticCustomError('value_error', f"fied2 should be in: {CONST_DATA}")
Когда намерено вызываешь ошибку выходит такой ответ:
{
"error": "Bad request",
"Not found": "[{'type': 'value_error', 'loc': ('body', 'field2'), 'msg': \"fied2 should be in: ['a', 'b']\", 'input': 'string'}]"
}
Можно ли как-то что-то переопределить, чтобы ошибка выходила вида:
{
"error": "fied2 should be in: ['a', 'b']",
"success": false
}
Ответы (2 шт):
Автор решения: NEStenerus nester
→ Ссылка
Примерно вот так:
from fastapi import FastAPI, Request
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from pydantic import BaseModel, ValidationError, validator
from pydantic.errors import PydanticTypeError
CONST_DATA = ['a', 'b']
class Sample(BaseModel):
field1: str
field2: str
@validator("field2")
def validate_field2(cls, value):
if value in CONST_DATA:
return value
raise PydanticTypeError(
code='value_error',
msg_template=f'field2 should be in: {CONST_DATA}',
)
app = FastAPI()
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: ValidationError):
errors = exc.errors()
print(errors)
for error in errors:
if error.get('ctx', {}).get('code', '') == 'value_error':
return JSONResponse(
status_code=400,
content={"error": error['msg'], "success": False},
)
return JSONResponse(
status_code=400,
content={"error": "Invalid input", "success": False},
)
@app.post("/sample/")
async def create_sample(sample: Sample):
return sample
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
Автор решения: Алексей
→ Ссылка
Оставлю свой вариант решения (благодаря комментарию @insolor нашел решение) - мне кажется он более лаконичен, чем предоставленный.
from fastapi import Request
class CustomException(Exception):
def __init__(self, message: str):
self.message = message
CONST_DATA = ['a', 'b']
class Sample(BaseModel):
field1: str
field2: str
@validator("field2")
def validate_fied2(cls, value):
if value in CONST_DATA:
return value
raise CustomException(message=f"field2 should be in: {CONST_DATA}")
@app.exception_handler(CustomException)
async def unicorn_exception_handler(request: Request, exc: CustomException):
return JSONResponse(
status_code=418,
content={"success": False,
"error": exc.message},
)
При вызове ошибки отработает как надо:
{
"success": false,
"error": "field2 should be in: ['a', 'b']"
}
Можно, конечно еще накидать еще параметры какие на входе были, но это уже будет громоздко и смысл потеряется