使用 Python 和 Pydantic,如何向字段添加自定义验证并让它返回与 Pydantic 发现的其他错误内联的错误?

问题描述 投票:0回答:1

我有一个搜索端点模型,如下所示:

class ArtistInboundSearchModel(BaseModel):
    ids: Optional[str] = Query(default=None)
    name: Optional[str] = Query(default=None)
    name_like: Optional[str] = Query(default=None) 
    page: Optional[int] = Query(default=None) 
    page_length: Optional[int] = Query(default=None) 

正如预期的那样,如果我将“page_length”等于“dog”且“page”等于“cat”的模型发布到端点,我会收到 422 响应,因为 Pydantic 拦截请求并验证它。 正如预期的那样,这个 422 响应中有 2 个错误,每个验证失败都有一个错误:

回复“/artists?page=cat&page_length=dog”:

{
    "detail": [
        {
            "type": "int_parsing",
            "loc": [
                "query",
                "page"
            ],
            "msg": "Input should be a valid integer, unable to parse string as an integer",
            "input": "cat"
        },
        {
            "type": "int_parsing",
            "loc": [
                "query",
                "page_length"
            ],
            "msg": "Input should be a valid integer, unable to parse string as an integer",
            "input": "dog"
        }
    ]
}

太棒了。 现在我们来谈谈查询参数“ids”。 此查询参数的目的是允许请求者提供以逗号分隔的 ID 列表并将搜索限制为这些 ID。 我们需要验证 ids 输入并确保每个 id 都是有效的 guid,否则,当我们对字符串进行标记并尝试将它们转换为 ids 时,我们会遇到异常。

我发现的唯一真正的文档建议执行以下操作来实现属性验证器(validate_comma_delimited_ids 和generate_invalid_comma_delimited_ids_message 是我的;它们经过单元测试并按预期工作):


    @field_validator('ids')
    def ids_valid(cls, value: str): 
        results = validate_comma_delimited_ids(value)

        if(results is not None):
            message = generate_invalid_comma_delimited_ids_message("ids", results)

            raise ValueError(message)
        
        return value

这会执行正确的验证,如果通过,将返回一个未更改的值,供我标记并传递给 BL。 但是,如果验证失败,它不会将其添加到失败列表中,而是引发 ValueError,并且我会收到未处理错误的 500 响应。

我环顾四周,试图找到一些信息,也许是另一个参数,即错误滚动列表,或者类似的东西,但我就是找不到。

期望的行为,以及我期望从任何其他现代验证框架或我自己的验证框架获得的行为,是我可以让我的验证块将验证错误添加到运行列表中,以便它的工作方式如下:

回复“/artists?page=cat&page_length=dog?ids=notanid,ohboy”

{
    "detail": [
        {
            "type": "int_parsing",
            "loc": [
                "query",
                "page"
            ],
            "msg": "Input should be a valid integer, unable to parse string as an integer",
            "input": "cat"
        },
        {
            "type": "int_parsing",
            "loc": [
                "query",
                "page_length"
            ],
            "msg": "Input should be a valid integer, unable to parse string as an integer",
            "input": "dog"
        },
        {
            "type": "custom_parsing",
            "loc": [
                "query",
                "ids"
            ],
            "msg": "Property should be a comma-delimited list of valid uuidv4 values.",
            "input": "notanid,ohboy"
        }
    ]
}

或者真的是我想要的任何东西。 如何访问验证块中验证错误的滚动列表,以便我可以将失败推送给它并与 Pydantics 常规操作集成?

我想要一个解决方案,可以轻松地在模型中与其他验证定义一起定义自定义验证,因为这是其他框架所做的事情,也是我的开发人员的首选开发人员体验。 我相信 pydantic 本身并不坏,所以我认为必须有某种方法可以做到这一点,否则它真的不是构建 api 的有用工具。

python api validation pydantic pydantic-v2
1个回答
0
投票

FastAPI 不支持

Query
参数的 Pydantic 模型。它意外地适用于 Pydantic v.1,但不适用于 Pydantic v.2。

您只能将 Pydantic 模型用于

Body
参数和响应。

至于将这些参数作为

Body
参数传递,它会按您期望的方式工作:

from typing import Optional
from fastapi import FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field, field_validator


class ArtistInboundSearchModel(BaseModel):
    ids: Optional[str] = Field(default=None)
    page: Optional[int] = Field(default=None) 

    @field_validator('ids')
    def ids_valid(cls, value: str): 
        raise ValueError("-----")

app = FastAPI()

@app.post("/")
def get_index(a: ArtistInboundSearchModel):
    pass

def test_index():
    with TestClient(app) as client:
        resp = client.post("/", json={"page": "cat", "ids": ""})
        assert resp.status_code == 422
        data = resp.json()
        assert len(data["detail"]) == 2, data["detail"]
© www.soinside.com 2019 - 2024. All rights reserved.