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

Displaying of FastAPI validation errors to end users

我正在寻找一些库或代码示例来将 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" 的内容(针对各种可能的错误)以在 toasts 中显示。
  2. 用它来显示表单验证消息
  3. 如果可能,根据 api 描述自行生成表格

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

您可以引发 HTTPException,HTTPException 是一个正常的 Python 异常,带有与 API 相关的附加数据。但是你不能 return 你需要提高它,因为它是一个 Python 异常

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"
   }
}

我带着类似的问题来到这里 - 我最终处理了 RequestValidationError 以返回一个响应,其中每个字段都是该字段问题的数组。 对您请求的响应将变为(status_code=400)

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

在前端管理快餐栏通知非常方便,而且足够灵活。

这是处理程序


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}
        ),
    )