FastAPI / pydantic:使用空 Depends() 时不考虑 field_validator

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

我遵循此答案方法2,以便能够使用fastapi结合附加数据上传多个文件。运行良好。

开始实施附加数据的处理(包括使用 pydantic 的验证)后,我面临一个问题:

我的自定义 

BaseModel

在直接使用模型类时可以正常工作,但是当通过 FastAPI 和

field_validator
使用它时,它无法按预期工作。
关键点是我想使用python 

Depends()

并且我希望能够在附加数据(查询参数)中使用枚举的

Enum
。因此,我使用自定义验证器仅允许枚举中存在的名称。
当我手动初始化模型时,验证按预期工作:

names

将此与 FastAPI 应用程序结合显示出意外的行为:不考虑 field_validator。相反,使用模型类的默认行为。

服务器代码:

from enum import Enum from pydantic import BaseModel, field_validator, ValidationInfo, ValidationError class VehicleSubSystems(Enum): A = "A Verbose" B = "B Verbose" class EvaluationArguments(BaseModel): vehicle_sub_system: VehicleSubSystems @field_validator("vehicle_sub_system", mode='before') @classmethod def validate_vehicle_sub_system(cls, vehicle_sub_system: str, _info: ValidationInfo) -> VehicleSubSystems: """ Allows using the enum names instead of the values """ try: return VehicleSubSystems[vehicle_sub_system] except KeyError: raise ValueError(f"Can not find vehicle subsystem '{vehicle_sub_system}'. " f"Allowed values: {[e.name for e in VehicleSubSystems]}") def test_validation_is_performed(): """ Test that the validation is performed """ EvaluationArguments(vehicle_sub_system="A") try: EvaluationArguments(vehicle_sub_system="DOES_NOT_EXIST") except ValidationError: print("Test passed") else: print("Test failed") if __name__ == '__main__': test_validation_is_performed() # prints "Test passed" as expected

客户端代码:

import uvicorn from typing import List from fastapi import FastAPI, File, Depends, UploadFile app = FastAPI() def create_args(vehicle_sub_system: str): return EvaluationArguments(vehicle_sub_system=vehicle_sub_system) @app.post("/process-works") def process_works(files: List[UploadFile] = File(...), eval_args: EvaluationArguments = Depends(create_args)): return f"Got {len(files)} files and {eval_args}" @app.post("/process-fails") def process_fails(files: List[UploadFile] = File(...), eval_args: EvaluationArguments = Depends()): return f"Got {len(files)} files and {eval_args}" if __name__ == '__main__': uvicorn.run(app, host="0.0.0.0", port=8000)

import requests

if __name__ == '__main__':
    url = 'http://127.0.0.1:8000'
    files = [('files', open('d:/temp/a.txt', 'rb')), ('files', open('d:/temp/b.txt', 'rb'))]
    params = {"vehicle_sub_system": "A"}

    print("Calling process-works")
    resp = requests.post(url=f"{url}/process-works", params=params, files=files)
    print(resp.json())

    print("Calling process-fails")
    resp = requests.post(url=f"{url}/process-fails", params=params, files=files)
    print(resp.json())

    # Output
    # Calling process-works
    # Got 2 files and vehicle_sub_system=<VehicleSubSystems.A: 'A Verbose'>
    # Calling process-fails
    # {'detail': [{'type': 'enum', 'loc': ['query', 'vehicle_sub_system'], 'msg': "Input should be 'A Verbose' or 'B Verbose'", 'input': 'A', 'ctx': {'expected': "'A Verbose' or 'B Verbose'"}}]}

端点显示了预期的行为,但仅当使用单独的依赖项

process-works
模仿模型类的直接使用时。

Depends(create_args)

端点(使用

process-fails
)显示了问题。我希望
Depends()
只是让 FastAPI 调用模型类的 init 方法并按预期使用验证。但不知怎的,它只是忽略了它。
我不明白为什么,也许有人可以解释这里发生了什么,以及是否有没有解决方法的解决方案?

python dependency-injection enums fastapi pydantic
1个回答
0
投票
Depends()

将检查

Depends(x)
中的
args
,并填写参数。因此,在这种情况下,您应该将
x
传递给
x
参考:

https://fastapi.tiangolo.com/tutorial/dependency/classes-as-dependency/

如果你不喜欢写
Depends

函数,也许你可以使用

create_args
参考:

https://fastapi.tiangolo.com/tutorial/body-multiple-params/


我的例子
  • Body()
# client

import requests


if __name__ == '__main__':
    url = 'http://127.0.0.1:8000'

    params = {'fff': 'A'}

    resp = requests.get(
        url=f"{url}/ggg/",
        params=params,
    )
    print(resp.json())

    resp = requests.post(
        url=f"{url}/ppp/",
        json=params,
    )
    print(resp.json())

'''
{'fff': 'A Verbose'}
{'fff': 'A Verbose'}
'''

© www.soinside.com 2019 - 2024. All rights reserved.