FastAPI/pydantic: field_validator не учитывается при использовании пустого Depends() ⇐ Python
FastAPI/pydantic: field_validator не учитывается при использовании пустого Depends()
Я использую Метод 2 этого ответа, чтобы иметь возможность загружать несколько файлов в сочетании с дополнительными данными с помощью fastapi. Все работает нормально.
После начала реализации обработки дополнительных данных, включая проверку, с использованием BaseModel pydantic, я столкнулся с проблемой:
Мой собственный field_validator работает при непосредственном использовании класса модели, но не работает должным образом при использовании его через FastAPI и Depends().
Ключевым моментом является то, что я хочу использовать Enum Python и иметь возможность использовать имена Enum в дополнительных данных (параметрах запроса). По этой причине я использую собственный валидатор, чтобы разрешать только имена, существующие в перечислении.
Когда я инициализирую модель вручную, проверка работает как положено:
из импорта перечисления Enum из pydantic import BaseModel, field_validator, ValidationInfo, ValidationError класс VehicleSubSystems(Enum): A = "Многословный" B = "B Подробный" класс 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: """ Позволяет использовать имена перечислений вместо значений """ пытаться: вернуть VehicleSubSystems[vehicle_sub_system] кроме KeyError: поднять ValueError(f"Невозможно найти подсистему автомобиля '{vehicle_sub_system}'. " f"Допустимые значения: {[e.name для e в VehicleSubSystems]}") защита test_validation_is_performed(): """ Проверка выполнения проверки """ EvaluationArguments(vehicle_sub_system="A") пытаться: EvaluationArguments(vehicle_sub_system="DOES_NOT_EXIST") кроме ValidationError: print("Тест пройден") еще: print("Тест не пройден") если __name__ == '__main__': test_validation_is_performed() # печатает «Тест пройден», как и ожидалось Объединение этого с приложением FastAPI приводит к неожиданному поведению: поле_валидатор не учитывается. Вместо этого используется поведение класса модели по умолчанию.
Код сервера:
импортировать uvicorn от ввода списка импорта из fastapi импортировать FastAPI, File, Depends, UploadFile приложение = ФастAPI() Защиту create_args (vehicle_sub_system: str): return EvaluationArguments(vehicle_sub_system=vehicle_sub_system) @app.post("/process-works") defprocess_works(files: List[UploadFile] = File(...), eval_args: EvaluationArguments = Depends(create_args)): return f"Получено файлов {len(files)} и {eval_args}" @app.post("/process-fails") defprocess_fails(files: List[UploadFile] = File(...), eval_args: EvaluationArguments = Depends()): return f"Получено файлов {len(files)} и {eval_args}" если __name__ == '__main__': uvicorn.run(приложение, хост="0.0.0.0", порт=8000) Код клиента:
запросы на импорт если __name__ == '__main__': URL = 'http://127.0.0.1:8000' files = [('files', open('d:/temp/a.txt', 'rb')), ('files', open('d:/temp/b.txt', 'rb')) ] параметры = {"vehicle_sub_system": "A"} print("Вызов процесса-работает") resp = Requests.post(url=f"{url}/process-works", params=params, files=files) печать (соответственно.json()) print("Вызов процесса-сбой") resp = Requests.post(url=f"{url}/process-fails", params=params, files=files) печать (соответственно.json()) # Выход # Вызов процесса-работает # Получили 2 файла и Vehicle_sub_system= # Вызов процесса-сбой # {'detail': [{'type': 'enum', 'loc': ['query', 'vehicle_sub_system'], 'msg': "Ввод должен быть "A Verbose" или "B Verbose"", ' input': 'A', 'ctx': {'expected': "'A Verbose' или 'B Verbose'"}}]} Конечная точка process-works демонстрирует ожидаемое поведение, но только при использовании отдельной зависимости Depends(create_args), которая имитирует прямое использование класса модели.
>
Конечная точка process-fails (с использованием Depends()) показывает проблему. Я ожидаю, что Depends() просто заставляет FastAPI вызывать метод инициализации класса модели и использует проверку, как и ожидалось. Но почему-то он просто игнорирует это.
Я не смог понять почему, возможно кто-нибудь сможет объяснить, что здесь происходит и есть ли решение без обходного пути?
Я использую Метод 2 этого ответа, чтобы иметь возможность загружать несколько файлов в сочетании с дополнительными данными с помощью fastapi. Все работает нормально.
После начала реализации обработки дополнительных данных, включая проверку, с использованием BaseModel pydantic, я столкнулся с проблемой:
Мой собственный field_validator работает при непосредственном использовании класса модели, но не работает должным образом при использовании его через FastAPI и Depends().
Ключевым моментом является то, что я хочу использовать Enum Python и иметь возможность использовать имена Enum в дополнительных данных (параметрах запроса). По этой причине я использую собственный валидатор, чтобы разрешать только имена, существующие в перечислении.
Когда я инициализирую модель вручную, проверка работает как положено:
из импорта перечисления Enum из pydantic import BaseModel, field_validator, ValidationInfo, ValidationError класс VehicleSubSystems(Enum): A = "Многословный" B = "B Подробный" класс 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: """ Позволяет использовать имена перечислений вместо значений """ пытаться: вернуть VehicleSubSystems[vehicle_sub_system] кроме KeyError: поднять ValueError(f"Невозможно найти подсистему автомобиля '{vehicle_sub_system}'. " f"Допустимые значения: {[e.name для e в VehicleSubSystems]}") защита test_validation_is_performed(): """ Проверка выполнения проверки """ EvaluationArguments(vehicle_sub_system="A") пытаться: EvaluationArguments(vehicle_sub_system="DOES_NOT_EXIST") кроме ValidationError: print("Тест пройден") еще: print("Тест не пройден") если __name__ == '__main__': test_validation_is_performed() # печатает «Тест пройден», как и ожидалось Объединение этого с приложением FastAPI приводит к неожиданному поведению: поле_валидатор не учитывается. Вместо этого используется поведение класса модели по умолчанию.
Код сервера:
импортировать uvicorn от ввода списка импорта из fastapi импортировать FastAPI, File, Depends, UploadFile приложение = ФастAPI() Защиту create_args (vehicle_sub_system: str): return EvaluationArguments(vehicle_sub_system=vehicle_sub_system) @app.post("/process-works") defprocess_works(files: List[UploadFile] = File(...), eval_args: EvaluationArguments = Depends(create_args)): return f"Получено файлов {len(files)} и {eval_args}" @app.post("/process-fails") defprocess_fails(files: List[UploadFile] = File(...), eval_args: EvaluationArguments = Depends()): return f"Получено файлов {len(files)} и {eval_args}" если __name__ == '__main__': uvicorn.run(приложение, хост="0.0.0.0", порт=8000) Код клиента:
запросы на импорт если __name__ == '__main__': URL = 'http://127.0.0.1:8000' files = [('files', open('d:/temp/a.txt', 'rb')), ('files', open('d:/temp/b.txt', 'rb')) ] параметры = {"vehicle_sub_system": "A"} print("Вызов процесса-работает") resp = Requests.post(url=f"{url}/process-works", params=params, files=files) печать (соответственно.json()) print("Вызов процесса-сбой") resp = Requests.post(url=f"{url}/process-fails", params=params, files=files) печать (соответственно.json()) # Выход # Вызов процесса-работает # Получили 2 файла и Vehicle_sub_system= # Вызов процесса-сбой # {'detail': [{'type': 'enum', 'loc': ['query', 'vehicle_sub_system'], 'msg': "Ввод должен быть "A Verbose" или "B Verbose"", ' input': 'A', 'ctx': {'expected': "'A Verbose' или 'B Verbose'"}}]} Конечная точка process-works демонстрирует ожидаемое поведение, но только при использовании отдельной зависимости Depends(create_args), которая имитирует прямое использование класса модели.
>
Конечная точка process-fails (с использованием Depends()) показывает проблему. Я ожидаю, что Depends() просто заставляет FastAPI вызывать метод инициализации класса модели и использует проверку, как и ожидалось. Но почему-то он просто игнорирует это.
Я не смог понять почему, возможно кто-нибудь сможет объяснить, что здесь происходит и есть ли решение без обходного пути?
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
FastAPI/pydantic: field_validator не учитывается при использовании пустого Depends()
Anonymous » » в форуме Python - 0 Ответы
- 23 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Наследует help_text из django.db.models.Field в rest_framework.serializer.Field
Anonymous » » в форуме Python - 0 Ответы
- 70 Просмотры
-
Последнее сообщение Anonymous
-