swagger 向最终用户显示FastAPI验证错误

xnifntxz  于 2022-11-06  发布在  其他
关注(0)|答案(3)|浏览(230)

我正在寻找一些库或代码示例,以将FastAPI验证消息格式化为人类可读的格式。例如,此端点:

@app.get("/")
async def hello(name: str):
    return {"hello": name}

如果缺少name查询参数,将生成下一个json输出:

{ 
    "detail":[ 
        { 
            "loc":[ 
                "query",
                "name"
            ],
            "msg":"field required",
            "type":"value_error.missing"
        }
    ]
}

所以我的问题是,如何:
1.将其转换为类似于“name field is required”(对于所有可能的错误)的内容,以便在toast中显示。
1.使用它来显示表单验证消息
1.如果可能的话,从api描述生成表单本身

bvpmtnay

bvpmtnay1#

FastAPI具有出色的异常处理功能,因此您可以通过多种方式自定义异常。

你可以引发一个HTTPException,HTTPException是一个普通的Python异常,包含了与API相关的附加数据。

from fastapi import HTTPException
...
@app.get("/")
async def hello(name: str):
    if not name:
        raise HTTPException(status_code=404, detail="Name field is required")
    return {"Hello": name}

通过将name: str添加为查询参数,它将自动变为必需参数,因此您需要添加Optional

from typing import Optional
...
@app.get("/")
async def hello(name: Optional[str] = None):
    error = {"Error": "Name field is required"}
    if name:
        return {"Hello": name}
    return error

$ curl 127.0.0.1:8000/?name=imbolc
{"Hello":"imbolc"}
...
$ curl 127.0.0.1:8000
{"Error":"Name field is required"}

但在您的情况下,我认为这是处理FastAPI重写validation_exception_handler中的错误的最佳方式:

from fastapi import FastAPI, Request, status
from fastapi.encoders import jsonable_encoder
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
...
@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(), "Error": "Name field is missing"}),
    )
...
@app.get("/")
async def hello(name: str):
    return {"hello": name}

您将得到这样的响应:

$ curl 127.0.0.1:8000

 {
   "detail":[
      {
         "loc":[
            "query",
            "name"
         ],
         "msg":"field required",
         "type":"value_error.missing"
      }
   ],
   "Error":"Name field is missing"
}

您可以自定义您的content,但如果你喜欢:

{
"Error":"Name field is missing",
   "Customize":{
      "This":"content",
      "Also you can":"make it simpler"
   }
}
pieyvz9o

pieyvz9o2#

我带着一个类似的问题来到这里--最后我处理了RequestValidationError,给予了一个响应,其中每个字段都是该字段的问题数组。

{
        "detail": "Invalid request",
        "errors": {"name": ["field required"]}
    }

这对于在snackbar通知的前端进行管理非常方便,并且足够灵活。
这是负责人

from collections import defaultdict

from fastapi import status
from fastapi.encoders import jsonable_encoder
from fastapi.responses import JSONResponse

@app.exception_handler(RequestValidationError)
async def custom_form_validation_error(request, exc):
    reformatted_message = defaultdict(list)
    for pydantic_error in exc.errors():
        loc, msg = pydantic_error["loc"], pydantic_error["msg"]
        filtered_loc = loc[1:] if loc[0] in ("body", "query", "path") else loc
        field_string = ".".join(filtered_loc)  # nested fields with dot-notation
        reformatted_message[field_string].append(msg)

    return JSONResponse(
        status_code=status.HTTP_400_BAD_REQUEST,
        content=jsonable_encoder(
            {"detail": "Invalid request", "errors": reformatted_message}
        ),
    )
6jjcrrmo

6jjcrrmo3#

我想我能想到的最好的答案是PlainTextResponse
添加以下内容:

from fastapi.exceptions import RequestValidationError

@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
    return PlainTextResponse(str(exc), status_code=400)

您会得到一个更人性化的错误消息,如以下纯文本格式:
在这里的FastAPI文档中有详细的说明。

相关问题