Веб-версияОткрыть в Telegram

Пост🔩 Если вам понадобится в рантайме поменить тип принимаемого объекта в роуте FastAPI, вот вам небольшой рецепт.

15 июня 2025
К
Коробка с питоном
🔩 Если вам понадобится в рантайме поменить тип принимаемого объекта в роуте FastAPI, вот вам небольшой рецепт. 😆 Для одного проекта я решил сделать плагин-систему, которая автоматически регистрирует python-файлы и добавляет эндпоинты в API написанном на FastAPI. Так как я использую OpenAPI, очень хочется, чтобы принимаемые и возвращаемые типы отображались в нём корректно. ➡️Допустим, есть у меня вот такой код, создающий эндпоинты в зависимости от переданного Action: class Action[ReqT, RespT](Protocol): name: str request_schema: Type[ReqT] # тип который мы будем принимать response_schema: Type[RespT] # тип который мы будем возвращать interact: Callable[[ReqT], Coroutine[Any, Any, RespT]] def create_action_handler(action: Action): # какой-то код async def action_endpoint(entity_id: int, data: dict[str, Any]) -> Any: # какой-то код return await action.interact(server, data) return action_endpoint ➡️ А вот так я добавляю нашу ручку в роутер: def add_action_route(router: APIRouter, action: Action): handler = create_action_handler(action) router.post( f"/plugins/{action.name}", response_model=action.response_schema, # установим схему для ответа )(handler) Схему для ответа я установил при регистрации нашего эндпоинта в response_model. А что делать с data, тип которого должен быть не dict[str, Any] а action.request_schema ❓ ℹ️ Для начала, я подумал, что раз FastAPI строит доку из аннотаций, наверное я смогу поменять аннотации и на этом дело сделано: handler = create_action_handler(action) handler.__annotations__["data"] = action.request_schema Но это не помогло - аннотации поменялись, а вот схема - нет 🍺 ! 😱 Оказывается, FastAPI не использует аннотации, а использует запеченные Signature, которые собираются из Dependency. При чем, в понимании FastAPI, dependency не только источник каких-то функций, а еще и наших схем. А дальше он из них и строит OpenAPI. Зная это нам остается только одно - изменить signature перед регистрацией роута 😱: sig = inspect.signature(handler) # достаем сигнатуру new = [] for p in sig.parameters.values(): if p.name == "data": # находим нашу data p = p.replace(annotation=action.request_schema) # меняем new.append(p) handler.__signature__ = sig.replace(parameters=new) # записываем новую сигнатуру Вуаля! Теперь в OpenAPI будет указанная в action.request_schema схема 👏 #fastapi #рецепт
12 · 747 ·

Рядом в ленте

ККоробка с питоном😎ovld - перегрузка функций по-человечески 👩‍💻 Наверняка любой из нас когда-то писал код по типу этого: def process(x: str | int) -> None: if isinstance(x, int):ККоробка с питоном💡 asyncssh - асинхронный ssh клиент и не только 👀 Если вы будете искать асинхронную альтернативу paramiko (это реализация SSHv2 на чистом питоне), то скорее все
это сообщение
ККоробка с питономКоробка с питоном@boxwithpython · канал · Технологии
488подписчиков154постов в индексе
Лента площадки Открыть в Telegram

Открытая публичная лента из поискового индекса ChatCrawler — «Google по публичному Telegram»; обновляется по мере обхода площадки. Время — UTC.

Только публичный контент, официальный API Telegram. О проекте · Вопросы · Чего мы не делаем · Убрать страницу из выдачи · Каталог · Поиск · Как мы считаем