--- title: Преобразовать публичные поля в тело запроса description: Отделите удобную сигнатуру SDK от структуры документа внешнего API. sources: - eazy_sdk.request.Body - eazy_sdk.request.BodyProjection - eazy_sdk.request.JsonPolicy - eazy_sdk.request.Wire - eazy_sdk.request.FieldOrder - eazy_sdk.request.QueryCodec - eazy_sdk.serialization.Serialization api_fingerprint: "sha256:2a67169f85189e5a301a3759eda9f01b43c56f048850fbd8290b41554dc4288e" --- Используйте `BodyProjection`, когда вызывающий передаёт плоские предметные значения, а внешний API ждёт вложенный служебный документ. Проекция выполняется для каждой попытки и возвращает структуру, которую затем кодирует выбранное представление тела. :::::{grid} 1 1 2 2 :class-container: http-exchange :gutter: 2 ::::{grid-item} :class: http-panel http-panel--request **→ Request** · ``POST /register`` ```json { "account": {"login": "ada", "email": "ada@mail.example"}, "client": "python" } ``` :::: ::::{grid-item} :class: http-panel http-panel--response **← Response** · ``201 Created`` ```json {"id": "account-42", "login": "ada"} ``` :::: ::::: ```{literalinclude} ../../../../../../examples/docs/request_projection.py :language: python :start-after: "# docs:projection:start" :end-before: "# docs:projection:end" ``` `target` описывает закрытую структуру на проводе. `using` получает значение операции и строит документ. `encoding=Body.json()` выбирает JSON, а `name` даёт проекции устойчивое имя для диагностики и схемы. :::{dropdown} Файл примера целиком ```{literalinclude} ../../../../../../examples/docs/request_projection.py :language: python ``` ::: Запуск: `uv run python examples/docs/request_projection.py`. ```text registered: ada as account-42 ``` ## Описать query одной моделью Сервис часто требует в query параметры, которые вызывающему не принадлежат: версии формата, флаги разбора, метку времени. Объявите query приватной моделью и передайте её в `__http__`: `query=QueryModel(ThreadQuery)`. Каждое поле модели становится одним параметром query, в порядке объявления. Поле операции без маркера размещения попадает в одноимённое поле модели. Остальные поля модели берут значения по умолчанию и в публичную сигнатуру не входят. | Что нужно | Как объявить в модели | |---|---| | постоянный параметр | поле со значением по умолчанию: `quotes_version: int = 1` | | значение на каждую попытку | поле с фабрикой: `default_factory=now_ms` | | параметр, который иногда не отправляется | поле со значением `None` | | составное значение в одном параметре | кодек на поле: `Annotated[Sort, Query(codec=JsonCodec())]` | Модель строится на каждой попытке запроса. Поэтому поле с фабрикой получает новое значение при повторе, переходе и повторной отправке после обновления сессии. Если одно значение уходит под двумя именами или поле вычисляется из других, передайте функцию: `QueryModel(ThreadQuery, using=build)`. Функция получает значение операции, а с двумя параметрами ещё и значения из `requires=`, как у `BodyProjection`. Модель query уживается с обычными полями `Query[...]`, с `Inject` и со значениями сессии. Они идут после полей модели; полный порядок задаёт `FieldOrder(query=...)`. Одно имя в двух местах отклоняется до отправки запроса. Поле с составным типом без кодека тоже отклоняется: один параметр несёт одно значение. Имя параметра на проводе берётся из модели. Адаптер pydantic читает псевдоним поля, только когда модель объявила `serialize_by_alias=True`. ## Разделить уровни представления | Уровень | Что он меняет | Где настраивается | |---|---|---| | имя поля | Python-имя в имя на проводе | маркер или адаптер модели | | документ | публичные поля в другую структуру | `BodyProjection` | | query | публичные поля и скрытые параметры сервиса | `QueryModel` | | порядок и строка запроса | стабильный порядок, кодирование пробелов | `Wire`, `FieldOrder`, `QueryCodec` | | JSON-байты | пробелы, ASCII, порядок ключей | `JsonPolicy` | | библиотека моделей | чтение и запись моделей | `Serialization` на корне или роутере | Не помещайте в проекцию авторизацию, капчу, CSRF и другие значения сессии. Их добавляют `Identity`, зависимости и политики защиты после построения предметного документа. ## Дальше - {doc}`Настройте модели и кодеки `. - {doc}`Подпишите окончательные байты `. - {doc}`Передайте значения через зависимости `.