7

在 FastAPI 框架中,pydantic 错误消息如下所示。

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

我想发送一个简单的消息:{"field-name":"error message"}

在他们提到的 Pydantic 文档中,在 try: except 块中创建模型实例并在 except 块中构造错误消息。但是在快速 API 中,模型实例由 fastapi 本身创建,例如,如果我编写如下所示的 URL

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

这里由 fastapi 本身创建的位置实例是问题所在。

有什么方法可以构造错误信息吗?

4

3 回答 3

7

实际上,此错误消息来自fastapi.exceptions,您可以通过覆盖自定义异常来实现,

想象一下我有这样的简单应用程序:

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

如果我将值无效值发送到我的请求正文

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

现在错误将更加自定义:

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

您可以更改异常的内容,一切由您决定。

于 2020-07-16T15:12:41.170 回答
1

我正在为它写一个中间件。

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
于 2020-02-18T06:15:47.240 回答
1

我不确定您是否会比其他答案更喜欢我的答案。您可以使用不同的错误消息创建自定义 pydantic。有点矫枉过正,但可以解决您的特定问题。在此示例中,当我插入未经许可的 HttpUrlSceme 时,我正在更改错误消息。

class UrlSchemePermittedError(errors.UrlError):
    code = 'url.scheme'
    msg_template = 'URL scheme not cool'

    def __init__(self, allowed_schemes: Set[str]):
        super().__init__(allowed_schemes=allowed_schemes)

class AnyHttpUrlDirrentMessage(AnyUrl):
    allowed_schemes = {'http', 'https'}
    @classmethod
    def validate_parts(cls, parts: Dict[str, str]) -> Dict[str, str]:
        """
        A method used to validate parts of an URL.
        Could be overridden to set default values for parts if missing
        """
        scheme = parts['scheme']
        if scheme is None:
            raise errors.UrlSchemeError()

        if cls.allowed_schemes and scheme.lower() not in cls.allowed_schemes:
            raise UrlSchemePermittedError(cls.allowed_schemes)

        port = parts['port']
        if port is not None and int(port) > 65_535:
            raise errors.UrlPortError()

        user = parts['user']
        if cls.user_required and user is None:
            raise errors.UrlUserInfoError()

        return parts
于 2021-12-17T09:39:57.193 回答