Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to change the pydantic error messages in fastAPI?

In the FastAPI framework, the pydantic error messages are showing like below.

{"detail": [
{
    "loc": [
        "body",
        "location",
        "name"
    ],
    "msg": "field required",
    "type": "value_error.missing"
},
{
    "loc": [
        "body",
        "location",
        "name12"
    ],
    "msg": "extra fields not permitted",
    "type": "value_error.extra"
}
]
}

I want to send a simple message: {"field-name":"error message"}.

In Pydantic document they mentioned like, create a model instance in the try: except blocks and construct the error message in the except block. But in fast API, model instance created by fastapi itself, for example, if I write an URL like below

@router.post("/", response_model=DataModelOut)
async def create_location(location: schemas.LocationIn, user: str = Depends(get_current_user) ):
return model.save(location,user)

Here the location instance created by fastapi itself is the problem.

Is there any way to construct the error message?

like image 363
user12747053 Avatar asked Feb 18 '20 05:02

user12747053


2 Answers

Actually this error messages coming from fastapi.exceptions, You can achieve that by overriding the custom exceptions,

Imagine i have simple app like this:

from fastapi import Request, status
from fastapi.encoders import jsonable_encoder
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from pydantic import BaseModel

@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
    return JSONResponse(
        status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
        content=jsonable_encoder({"detail": exc.errors(),
                "body": exc.body,
                 "your_additional_errors": {"Will be": "Inside", "This":" Error message"}}),
    )

class Item(BaseModel):
    title: str
    size: int

@app.post("/items/")
async def create_item(item: Item):
    return item

If i send values invalid values to my Request body

{
 "title": 22,
 "size": "hehe"
}

Now the error will be more customized:

{
  "detail": [
    {
      "loc": [
        "body",
        "size"
      ],
      "msg": "value is not a valid integer",
      "type": "type_error.integer"
    }
  ],
  "body": {
    "title": 22,
    "size": "hehe"
  },
  "your_additional_errors": {
    "Will be": "Inside the",
    "Error": "Message"
  }
}

You can change the content of exception, everything is up to you.

like image 174
Yagiz Degirmenci Avatar answered Nov 17 '22 04:11

Yagiz Degirmenci


I am writing a middle ware for it.

async def genrange(s):
    import json
    s = json.loads(s)
    yield json.dumps({"message":{k.get("loc")[-1]:k.get("msg") for k in s['detail']},
        "id":None})

@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    response = await call_next(request)
    status_code = response.status_code
    if status_code >=300:
        async for i in response.body_iterator:
            data = genrange(i)
        response.body_iterator = data
    return response
like image 1
user12747053 Avatar answered Nov 17 '22 04:11

user12747053