Вы можете ограничить количество строк из docstring *функции-обработчика пути*, используемых для OpenAPI.
Добавление `\f` (экранированного символа «form feed») заставит **FastAPI** обрезать вывод, используемый для OpenAPI, в этой точке.
Добавление `\f` (экранированного символа «form feed») заставит **FastAPI** обрезать текст, используемый для OpenAPI, в этой точке.
Это не отобразится в документации, но другие инструменты (например, Sphinx) смогут использовать остальное.
@ -135,7 +135,7 @@
Таким образом, вы можете добавить дополнительные данные к автоматически сгенерированной схеме.
Например, вы можете решить читать и валидировать HTTP-запрос своим кодом, не используя автоматические возможности FastAPI с Pydantic, но при этом захотите описать HTTP-запрос в схеме OpenAPI.
Например, вы можете решить читать и валидировать HTTP-запрос своим кодом, не используя автоматические возможности FastAPI и Pydantic, но при этом захотите описать HTTP-запрос в схеме OpenAPI.
# Разделять схемы OpenAPI для входа и выхода или нет { #separate-openapi-schemas-for-input-and-output-or-not }
С момента выхода **Pydantic v2** сгенерированный OpenAPI стал чуть более точным и **корректным**, чем раньше. 😎
При использовании **Pydantic v2** сгенерированный OpenAPI становится чуть более точным и **корректным**, чем раньше. 😎
На самом деле, в некоторых случаях в OpenAPI будет даже **две JSON Schema** для одной и той же Pydantic‑модели: для входа и для выхода — в зависимости от наличия **значений по умолчанию**.
На самом деле, в некоторых случаях в OpenAPI будет даже **две JSON-схемы** для одной и той же Pydantic‑модели: для входа и для выхода — в зависимости от наличия **значений по умолчанию**.
Посмотрим, как это работает, и как это изменить при необходимости.
@ -79,7 +79,7 @@
## Не разделять схемы { #do-not-separate-schemas }
Теперь бывают случаи, когда вы хотите иметь **одну и ту же схему для входа и выхода**.
Однако бывают случаи, когда вы хотите иметь **одну и ту же схему для входа и выхода**.
Главный сценарий — когда у вас уже есть сгенерированный клиентский код/SDK, и вы пока не хотите обновлять весь этот автогенерируемый клиентский код/SDK, вероятно, вы захотите сделать это в какой-то момент, но, возможно, не прямо сейчас.
Более полный пример с дополнительными возможностями см. в <ahref="https://fastapi.tiangolo.com/ru/tutorial/">Руководство - Руководство пользователя</a>.
Более полный пример с дополнительными возможностями см. в <ahref="https://fastapi.tiangolo.com/ru/tutorial/">Учебник - Руководство пользователя</a>.
**Осторожно, спойлер**: руководство - руководство пользователя включает:
**Осторожно, спойлер**: учебник - руководство пользователя включает:
* Объявление **параметров** из других источников: **HTTP-заголовки**, **cookies**, **поля формы** и **файлы**.
* Как задать **ограничения валидации** вроде `maximum_length` или `regex`.
@ -496,7 +496,7 @@ Deploying to FastAPI Cloud...
**<ahref="https://fastapicloud.com"class="external-link"target="_blank">FastAPI Cloud</a>** создан тем же автором и командой, что и **FastAPI**.
Он упрощает процесс **создания**, **развертывания** и **доступа** к API при минимальных усилиях.
Он упрощает процесс **создания образа**, **развертывания** и **доступа** к API при минимальных усилиях.
Он переносит тот же **опыт разработчика**, что и при создании приложений на FastAPI, на их **развертывание** в облаке. 🎉
* Всё помещается в каталоге `app`. В нём также находится пустой файл `app/__init__.py`. Таким образом, `app` является "Python-пакетом" (коллекцией "Python-модулей"): `app`.
* Он содержит файл `app/main.py`. Данный файл является частью Python-пакета (т.е. находится внутри каталога, содержащего файл `__init__.py`), и, соответственно, он является модулем этого пакета: `app.main`.
* Он также содержит файл `app/dependencies.py`, который также, как и `app/main.py`, является модулем: `app.dependencies`.
* Здесь также находится подкаталог `app/routers/`, содержащий `__init__.py`. Он является Python-субпакетом: `app.routers`.
* Здесь также находится подкаталог `app/routers/`, содержащий `__init__.py`. Он является Python-подпакетом: `app.routers`.
* Файл `app/routers/items.py` находится внутри пакета `app/routers/`. Таким образом, он является субмодулем: `app.routers.items`.
* Точно так же `app/routers/users.py` является ещё одним субмодулем: `app.routers.users`.
* Подкаталог `app/internal/`, содержащий файл `__init__.py`, является ещё одним Python-субпакетом: `app.internal`.
@ -58,22 +58,22 @@ from app.routers import items
```bash
.
├── app # "app" is a Python package
│ ├── __init__.py # this file makes "app" a "Python package"
│ ├── main.py # "main" module, e.g. import app.main
│ ├── dependencies.py # "dependencies" module, e.g. import app.dependencies
│ └── routers # "routers" is a "Python subpackage"
│ │ ├── __init__.py # makes "routers" a "Python subpackage"
│ │ ├── items.py # "items" submodule, e.g. import app.routers.items
│ │ └── users.py # "users" submodule, e.g. import app.routers.users
│ └── internal # "internal" is a "Python subpackage"
│ ├── __init__.py # makes "internal" a "Python subpackage"
│ └── admin.py # "admin" submodule, e.g. import app.internal.admin
├── app # "app" пакет
│ ├── __init__.py # этот файл превращает "app" в "Python-пакет"
Например, наличие `dependencies` в `APIRouter` можно использовать, чтобы требовать аутентификацию для целой группы*операций пути*. Даже если зависимости не добавляются по отдельности к каждой из них.
Например, с помощью зависимостей в `APIRouter` мы можем потребовать аутентификации для доступа ко всей группе*операций пути*. Даже если зависимости не добавляются по отдельности к каждой из них.
///
@ -263,7 +263,7 @@ from ...dependencies import get_token_header
то это бы означало:
* Начать в том же пакете, в котором находится этот модуль (файл `app/routers/items.py`) (каталог `app/routers/`)...
* Начать в том же пакете, в котором находится этот модуль (файл `app/routers/items.py`) расположен в (каталоге`app/routers/`)...
* перейти в родительский пакет (каталог `app/`)...
* затем перейти в родительский пакет этого пакета (родительского пакета нет, `app` — верхний уровень 😱)...
* и там найти модуль `dependencies` (файл `app/dependencies.py`)...
@ -289,7 +289,7 @@ from ...dependencies import get_token_header
///
## Основной`FastAPI` { #the-main-fastapi }
## Модуль main в`FastAPI` { #the-main-fastapi }
Теперь давайте посмотрим на модуль `app/main.py`.
@ -309,11 +309,11 @@ from ...dependencies import get_token_header
### Импорт `APIRouter` { #import-the-apirouter }
Теперь мы импортируем другие субмодули, содержащие `APIRouter`:
Теперь мы импортируем другие подмодули, содержащие `APIRouter`:
Так как файлы `app/routers/users.py` и `app/routers/items.py` являются субмодулями, входящими в один и тот же Python-пакет `app`, мы можем использовать одну точку `.` для импорта через «относительные импорты».
Так как файлы `app/routers/users.py` и `app/routers/items.py` являются подмодулями, входящими в один и тот же Python-пакет `app`, мы можем использовать одну точку `.` для импорта через «относительные импорты».
### Как работает импорт { #how-the-importing-works }
@ -325,9 +325,9 @@ from .routers import items, users
означает:
* Начать в том же пакете, в котором находится этот модуль (файл `app/main.py`) (каталог `app/`)...
* найти субпакет `routers` (каталог `app/routers/`)...
* и импортировать из него субмодуль`items` (файл `app/routers/items.py`) и `users` (файл `app/routers/users.py`)...
* Начать в том же пакете, в котором находится этот модуль (файл `app/main.py`) расположен в (каталоге`app/`)...
* найти подпакет `routers` (каталог `app/routers/`)...
* и импортировать из него подмодули`items` (файл `app/routers/items.py`) и `users` (файл `app/routers/users.py`)...
В модуле `items` будет переменная `router` (`items.router`). Это та же самая, которую мы создали в файле `app/routers/items.py`, это объект `APIRouter`.
@ -359,9 +359,9 @@ from app.routers import items, users
Таким образом исходный `APIRouter`останется неизменённым, и мы сможем продолжать делиться этим же файлом `app/internal/admin.py` с другими проектами в организации.
Таким образом исходный `APIRouter`не будет модифицирован, и мы сможем использовать файл `app/internal/admin.py` сразу в нескольких проектах организации.
В результате в нашем приложении каждая из *операций пути* из модуля `admin` будет иметь:
@ -479,9 +479,9 @@ $ fastapi dev app/main.py
</div>
И откройте документацию по адресу <ahref="http://127.0.0.1:8000/docs"class="external-link"target="_blank">http://127.0.0.1:8000/docs</a>.
Откройте документацию по адресу <ahref="http://127.0.0.1:8000/docs"class="external-link"target="_blank">http://127.0.0.1:8000/docs</a>.
Вы увидите автоматическую документацию API, включая пути из всех субмодулей, с использованием корректных путей (и префиксов) и корректных тегов:
Вы увидите автоматическую документацию API, включая пути из всех подмодулей, с использованием корректных путей (и префиксов) и корректных тегов:
* Сгенерировать `dict` без значений по умолчанию из входной модели (с использованием `exclude_unset`).
* Таким образом, можно обновлять только те значения, которые действительно установлены пользователем, вместо того чтобы переопределять значения, уже сохраненные, значениями по умолчанию из вашей модели.
* Таким образом, можно обновлять только те значения, которые действительно установлены пользователем, вместо того чтобы переопределять уже сохраненные значения значениями по умолчанию из вашей модели.
* Создать копию хранимой модели, обновив ее атрибуты полученными частичными обновлениями (с помощью параметра `update`).
* Преобразовать скопированную модель в то, что может быть сохранено в вашей БД (например, с помощью `jsonable_encoder`).
* Это сравнимо с повторным использованием метода модели `.model_dump()`, но при этом происходит проверка (и преобразование) значений в типы данных, которые могут быть преобразованы в JSON, например, `datetime` в `str`.
FastAPI будет использовать этот возвращаемый тип, чтобы:
* **Валидировать** возвращаемые данные.
* Если данные невалидны (например, отсутствует поле), это означает, что код *вашего* приложения работает некорректно и возвращает не то, что должен, и он вернёт ошибку сервера вместо неправильных данных. Так вы и ваши клиенты можете быть уверены, что получите ожидаемые данные и ожидаемую структуру данных.
* Если данные невалидны (например, отсутствует поле), это означает, что код *вашего* приложения работает некорректно и возвращает не то, что должен. В таком случае будет возвращена ошибка сервера вместо неправильных данных. Так вы и ваши клиенты можете быть уверены, что получите ожидаемые данные и ожидаемую структуру данных.
* Добавить **JSON Schema** для ответа в OpenAPI *операции пути*.
* Это будет использовано **автоматической документацией**.
* Это также будет использовано инструментами автоматической генерации клиентского кода.
@ -23,7 +23,7 @@ FastAPI будет использовать этот возвращаемый т
Бывают случаи, когда вам нужно или хочется возвращать данные, которые не в точности соответствуют объявленному типу.
Например, вы можете хотеть **возвращать словарь** или объект из базы данных, но **объявить его как Pydantic-модель**. Тогда Pydantic-модель выполнит всё документирование данных, валидацию и т.п. для объекта, который вы вернули (например, словаря или объекта из базы данных).
Например, вы можете хотеть **возвращать словарь** или объект из базы данных, но **объявить его как Pydantic-модель**. Тогда Pydantic-модель выполнит документирование данных, валидацию и т.п. для объекта, который вы вернули (например, словаря или объекта из базы данных).
Если вы добавите аннотацию возвращаемого типа, инструменты и редакторы кода начнут жаловаться (и будут правы), что функция возвращает тип (например, dict), отличный от объявленного (например, Pydantic-модель).
@ -41,13 +41,13 @@ FastAPI будет использовать этот возвращаемый т
/// note | Примечание
Обратите внимание, что `response_model` — это параметр метода «декоратора» (`get`, `post` и т.д.), а не вашей *функции-обработчика пути*, в которой указываются все параметры и тело запроса.
Обратите внимание, что `response_model` — это параметр метода «декоратора» (`get`, `post` и т.д.), а не вашей *функции-обработчика пути*, в которой указываются параметры и тело запроса.
///
`response_model` принимает тот же тип, что вы бы объявили для поля Pydantic-модели, то есть это может быть одна Pydantic-модель, а может быть, например, `list` Pydantic-моделей, как `List[Item]`.
FastAPI будет использовать этот `response_model` для документирования данных, валидации и т.п., а также для **конвертации и фильтрации выходных данных** к объявленному типу.
FastAPI будет использовать этот `response_model` для документирования, валидации данных и т.п., а также для **конвертации и фильтрации выходных данных** к объявленному типу.
## Возвращаемый тип и фильтрация данных { #return-type-and-data-filtering }
Продолжим предыдущий пример. Мы хотели **аннотировать функцию одним типом**, но при этом хотели иметь возможность вернуть из функции что-то, что фактически включает **больше данных**.
Продолжим предыдущий пример. Мы хотели **аннотировать функцию одним типом**, но при этом иметь возможность вернуть из функции что-то, что фактически включает **больше данных**.
Мы хотим, чтобы FastAPI продолжал **фильтровать** данные с помощью модели ответа. Так что, даже если функция возвращает больше данных, в ответ будут включены только поля, объявленные в модели ответа.
@ -181,7 +181,7 @@ FastAPI делает несколько вещей внутри вместе с
Самый распространённый случай — [возвращать Response напрямую, как описано далее в продвинутой документации](../advanced/response-directly.md){.internal-link target=_blank}.
Самый распространённый случай — [возвращать Response напрямую, как описано далее в разделах документации для продвинутых](../advanced/response-directly.md){.internal-link target=_blank}.
@ -211,7 +211,7 @@ FastAPI делает несколько вещей внутри вместе с
Продолжая пример выше, вы можете не хотеть использовать стандартные валидацию данных, документирование, фильтрацию и т.п., выполняемые FastAPI.
Но при этом вы можете хотеть сохранить аннотацию возвращаемого типа в функции, чтобы пользоваться поддержкой инструментов вроде редакторов кода и проверяющих типов инструментов (например, mypy).
Но при этом вы можете хотеть сохранить аннотацию возвращаемого типа в функции, чтобы пользоваться поддержкой инструментов вроде редакторов кода и инструментов проверки типов (например, mypy).
В этом случае вы можете отключить генерацию модели ответа, установив `response_model=None`:
@ -80,13 +80,13 @@ OpenAPI 3.1.0 (используется начиная с FastAPI 0.99.0) доб
Ещё до того как **JSON Schema** поддержала `examples`, в OpenAPI была поддержка другого поля, также называемого `examples`.
Эти **специфические для OpenAPI**`examples` находятся в другой секции спецификации OpenAPI. Они находятся в **подробностях для каждой операции пути (обработчика пути)**, а не внутри каждого объекта JSON Schema.
Эти **специфические для OpenAPI**`examples` находятся в другой секции спецификации OpenAPI. Они находятся в **подробностях для каждой операции пути (обработчика пути)**, а не внутри каждого объекта Schema.
И Swagger UI уже какое‑то время поддерживает именно это поле `examples`. Поэтому вы можете использовать его, чтобы **отобразить** разные **примеры в UI документации**.
Структура этого специфичного для OpenAPI поля `examples` — это `dict` с **несколькими примерами** (вместо `list`), каждый с дополнительной информацией, которая также будет добавлена в **OpenAPI**.
Это не помещается внутрь каждого объекта JSON Schema в OpenAPI, это находится снаружи, непосредственно на уровне самой *операции пути*.
Это не помещается внутрь каждого объекта Schema в OpenAPI, это находится снаружи, непосредственно на уровне самой *операции пути*.
### Использование параметра `openapi_examples` { #using-the-openapi-examples-parameter }
@ -113,7 +113,7 @@ OpenAPI 3.1.0 (используется начиная с FastAPI 0.99.0) доб