Sync fastapi docs from 7cb06f36 on 2026-07-11

This commit is contained in:
The Librarian
2026-07-11 04:00:12 +00:00
parent 2c5483ee1c
commit d71a936809
1032 changed files with 12357 additions and 6438 deletions
+2 -2
View File
@@ -258,7 +258,7 @@ works(foo="bar") # Это работает 🎉
* `bar` как `str`
* `baz` как `list`
* Учебник Руководство пользователя
* Учебник - Руководство пользователя
* Расширенное руководство пользователя
* Документация по SQLModel
* Документация API
@@ -461,7 +461,7 @@ works(foo="bar") # Это работает 🎉
* библиотека
* lifespan
* блокировка
* middleware (Промежуточный слой)
* middleware (промежуточный слой)
* мобильное приложение
* модуль
* монтирование
@@ -34,7 +34,7 @@
///
/// info | Информация
/// note | Примечание
Ключ `model` не является частью OpenAPI.
@@ -183,7 +183,7 @@
///
/// info | Информация
/// note | Примечание
Если вы явно не укажете другой тип содержимого в параметре `responses`, FastAPI будет считать, что ответ имеет тот же тип содержимого, что и основной класс ответа (по умолчанию `application/json`).
@@ -1,5 +1,6 @@
# Дополнительные статус-коды { #additional-status-codes }
По умолчанию **FastAPI** будет возвращать ответы, используя `JSONResponse`, помещая содержимое, которое вы возвращаете из вашей *операции пути*, внутрь этого `JSONResponse`.
Он будет использовать статус-код по умолчанию или тот, который вы укажете в вашей *операции пути*.
@@ -36,7 +36,7 @@
{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *}
Так мы «параметризуем» нашу зависимость: теперь внутри неё хранится "bar" в атрибуте `checker.fixed_content`.
Так мы «параметризуем» нашу зависимость: теперь внутри неё хранится `"bar"` в атрибуте `checker.fixed_content`.
## Используем экземпляр как зависимость { #use-the-instance-as-a-dependency }
@@ -48,7 +48,7 @@
checker(q="somequery")
```
…и передаст возвращённое значение как значение зависимости в параметр `fixed_content_included` нашей *функции-обработчику пути*:
…и передаст возвращённое значение как значение зависимости в нашу *функцию-обработчик пути* в параметр `fixed_content_included`:
{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *}
@@ -98,7 +98,7 @@ checker(q="somequery")
В версии 0.118.0 это поведение было возвращено к тому, что код после `yield` выполняется после отправки ответа.
/// info | Информация
/// note | Примечание
Как вы увидите ниже, это очень похоже на поведение до версии 0.106.0, но с несколькими улучшениями и исправлениями краевых случаев.
+2 -2
View File
@@ -41,7 +41,7 @@
{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *}
/// info | Информация
/// note | Примечание
Параметр `response_class` также используется для указания «типа содержимого» ответа.
@@ -65,7 +65,7 @@
///
/// info | Информация
/// note | Примечание
Разумеется, фактический заголовок `Content-Type`, статус-код и т.д. возьмутся из объекта `Response`, который вы вернули.
+4 -4
View File
@@ -12,13 +12,13 @@ FastAPI построен поверх **Pydantic**, и я показывал в
И, конечно, поддерживаются те же возможности:
- валидация данных
- сериализация данных
- документирование данных и т.д.
* валидация данных
* сериализация данных
* документирование данных и т.д.
Это работает так же, как с Pydantic-моделями. И на самом деле под капотом это достигается тем же образом, с использованием Pydantic.
/// info | Информация
/// note | Примечание
Помните, что dataclasses не умеют всего того, что умеют Pydantic-модели.
+29 -29
View File
@@ -1,30 +1,30 @@
# События lifespan { #lifespan-events }
Вы можете определить логику (код), которую нужно выполнить перед тем, как приложение начнет запускаться. Это означает, что этот код будет выполнен один раз, перед тем как приложение начнет получать HTTP-запросы.
Вы можете определить логику (код), которую нужно выполнить перед тем, как приложение **запустится**. Это означает, что этот код будет выполнен **один раз**, **перед** тем как приложение **начнет получать HTTP-запросы**.
Аналогично, вы можете определить логику (код), которую нужно выполнить, когда приложение завершает работу. В этом случае код будет выполнен один раз, после обработки, возможно, многих запросов.
Аналогично, вы можете определить логику (код), которую нужно выполнить, когда приложение **завершает работу**. В этом случае код будет выполнен **один раз**, **после обработки**, возможно, **многих HTTP-запросов**.
Поскольку этот код выполняется до того, как приложение начинает принимать запросы, и сразу после того, как оно заканчивает их обрабатывать, он охватывает весь lifespan (жизненный цикл) приложения (слово «lifespan» станет важным через секунду 😉).
Поскольку этот код выполняется до того, как приложение **начинает** принимать HTTP-запросы, и сразу после того, как оно **заканчивает** их обрабатывать, он охватывает весь **lifespan** (жизненный цикл) приложения (слово «lifespan» станет важным через секунду 😉).
Это может быть очень полезно для настройки ресурсов, которые нужны для всего приложения, которые разделяются между запросами и/или которые нужно затем очистить. Например, пул подключений к базе данных или загрузка общей модели Машинного обучения.
Это может быть очень полезно для настройки **ресурсов**, которые нужны для всего приложения, которые **разделяются** между HTTP-запросами и/или которые нужно затем **очистить**. Например, пул подключений к базе данных или загрузка общей модели Машинного обучения.
## Вариант использования { #use-case }
Начнем с примера варианта использования, а затем посмотрим, как это решить.
Начнем с примера **варианта использования**, а затем посмотрим, как это решить.
Представим, что у вас есть несколько моделей Машинного обучения, которые вы хотите использовать для обработки запросов. 🤖
Представим, что у вас есть несколько **моделей Машинного обучения**, которые вы хотите использовать для обработки HTTP-запросов. 🤖
Эти же модели разделяются между запросами, то есть это не одна модель на запрос, не одна на пользователя и т.п.
Эти же модели разделяются между HTTP-запросами, то есть это не одна модель на HTTP-запрос, не одна на пользователя и т.п.
Представим, что загрузка модели может занимать довольно много времени, потому что ей нужно прочитать много данных с диска. Поэтому вы не хотите делать это для каждого запроса.
Представим, что загрузка модели может **занимать довольно много времени**, потому что ей нужно прочитать много **данных с диска**. Поэтому вы не хотите делать это для каждого HTTP-запроса.
Вы могли бы загрузить её на верхнем уровне модуля/файла, но это означало бы, что модель загружается даже если вы просто запускаете простой автоматический тест; тогда этот тест будет медленным, так как ему придется ждать загрузки модели перед запуском независимой части кода.
Вы могли бы загрузить её на верхнем уровне модуля/файла, но это означало бы, что модель будет **загружаться** даже если вы просто запускаете простой автоматический тест; тогда этот тест будет **медленным**, так как ему придется ждать загрузки модели перед запуском независимой части кода.
Именно это мы и решим: давайте загружать модель перед тем, как начнётся обработка запросов, но только непосредственно перед тем, как приложение начнет принимать запросы, а не во время загрузки кода.
Именно это мы и решим: давайте загружать модель перед тем, как начнётся обработка HTTP-запросов, но только непосредственно перед тем, как приложение начнет принимать HTTP-запросы, а не во время загрузки кода.
## Lifespan { #lifespan }
Вы можете определить логику для startup и shutdown, используя параметр `lifespan` приложения `FastAPI` и «менеджер контекста» (через секунду покажу что это).
Вы можете определить логику для *startup* и *shutdown*, используя параметр `lifespan` приложения `FastAPI` и «менеджер контекста» (через секунду покажу что это).
Начнем с примера, а затем разберём его подробнее.
@@ -32,13 +32,13 @@
{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *}
Здесь мы симулируем дорогую операцию startup по загрузке модели, помещая (фиктивную) функцию модели в словарь с моделями Машинного обучения до `yield`. Этот код будет выполнен до того, как приложение начнет принимать запросы, во время startup.
Здесь мы симулируем дорогую операцию *startup* по загрузке модели, помещая (фиктивную) функцию модели в словарь с моделями Машинного обучения до `yield`. Этот код будет выполнен **до** того, как приложение **начнет принимать HTTP-запросы**, во время *startup*.
А затем сразу после `yield` мы выгружаем модель. Этот код будет выполнен после того, как приложение закончит обрабатывать запросы, непосредственно перед shutdown. Это может, например, освободить ресурсы, такие как память или GPU.
А затем сразу после `yield` мы выгружаем модель. Этот код будет выполнен **после** того, как приложение **закончит обрабатывать HTTP-запросы**, непосредственно перед *shutdown*. Это может, например, освободить ресурсы, такие как память или GPU.
/// tip | Совет
`shutdown` произойдёт, когда вы останавливаете приложение.
`shutdown` произойдёт, когда вы **останавливаете** приложение.
Возможно, вам нужно запустить новую версию, или вы просто устали от него. 🤷
@@ -50,26 +50,26 @@
{* ../../docs_src/events/tutorial003_py310.py hl[14:19] *}
Первая часть функции, до `yield`, будет выполнена до запуска приложения.
Первая часть функции, до `yield`, будет выполнена **до** запуска приложения.
А часть после `yield` будет выполнена после завершения работы приложения.
А часть после `yield` будет выполнена **после** завершения работы приложения.
### Асинхронный менеджер контекста { #async-context-manager }
Если присмотреться, функция декорирована `@asynccontextmanager`.
Это превращает функцию в «асинхронный менеджер контекста».
Это превращает функцию в «**асинхронный менеджер контекста**».
{* ../../docs_src/events/tutorial003_py310.py hl[1,13] *}
Менеджер контекста в Python — это то, что можно использовать в операторе `with`. Например, `open()` можно использовать как менеджер контекста:
**Менеджер контекста** в Python — это то, что можно использовать в операторе `with`. Например, `open()` можно использовать как менеджер контекста:
```Python
with open("file.txt") as file:
file.read()
```
В последних версиях Python есть также асинхронный менеджер контекста. Его используют с `async with`:
В последних версиях Python есть также **асинхронный менеджер контекста**. Его используют с `async with`:
```Python
async with lifespan(app):
@@ -80,7 +80,7 @@ async with lifespan(app):
В нашем примере выше мы не используем его напрямую, а передаём его в FastAPI, чтобы он использовал его сам.
Параметр `lifespan` приложения `FastAPI` принимает асинхронный менеджер контекста, поэтому мы можем передать ему наш новый асинхронный менеджер контекста `lifespan`.
Параметр `lifespan` приложения `FastAPI` принимает **асинхронный менеджер контекста**, поэтому мы можем передать ему наш новый асинхронный менеджер контекста `lifespan`.
{* ../../docs_src/events/tutorial003_py310.py hl[22] *}
@@ -88,13 +88,13 @@ async with lifespan(app):
/// warning | Предупреждение
Рекомендуемый способ обрабатывать startup и shutdown — использовать параметр `lifespan` приложения `FastAPI`, как описано выше. Если вы укажете параметр `lifespan`, обработчики событий `startup` и `shutdown` больше вызываться не будут. Либо всё через `lifespan`, либо всё через события — не одновременно.
Рекомендуемый способ обрабатывать *startup* и *shutdown* — использовать параметр `lifespan` приложения `FastAPI`, как описано выше. Если вы укажете параметр `lifespan`, обработчики событий `startup` и `shutdown` больше вызываться не будут. Либо всё через `lifespan`, либо всё через события — не одновременно.
Эту часть, скорее всего, можно пропустить.
///
Есть альтернативный способ определить логику, которую нужно выполнить во время startup и во время shutdown.
Есть альтернативный способ определить логику, которую нужно выполнить во время *startup* и во время *shutdown*.
Вы можете определить обработчики событий (функции), которые нужно выполнить до старта приложения или при его завершении.
@@ -110,7 +110,7 @@ async with lifespan(app):
Вы можете добавить более одного обработчика события.
И ваше приложение не начнет принимать запросы, пока все обработчики события `startup` не завершатся.
И ваше приложение не начнет принимать HTTP-запросы, пока все обработчики события `startup` не завершатся.
### Событие `shutdown` { #shutdown-event }
@@ -120,7 +120,7 @@ async with lifespan(app):
Здесь функция-обработчик события `shutdown` запишет строку текста `"Application shutdown"` в файл `log.txt`.
/// info | Информация
/// note | Примечание
В функции `open()` параметр `mode="a"` означает «добавление» (append), то есть строка будет добавлена в конец файла, без перезаписи предыдущего содержимого.
@@ -140,7 +140,7 @@ async with lifespan(app):
### `startup` и `shutdown` вместе { #startup-and-shutdown-together }
С высокой вероятностью логика для вашего startup и shutdown связана: вы можете хотеть что-то запустить, а затем завершить, получить ресурс, а затем освободить его и т.д.
С высокой вероятностью логика для вашего *startup* и *shutdown* связана: вы можете хотеть что-то запустить, а затем завершить, получить ресурс, а затем освободить его и т.д.
Делать это в отдельных функциях, которые не разделяют общую логику или переменные, сложнее, так как придётся хранить значения в глобальных переменных или использовать похожие приёмы.
@@ -148,11 +148,11 @@ async with lifespan(app):
## Технические детали { #technical-details }
Немного технических подробностей для любопытных умников. 🤓
Просто техническая подробность для любопытных умников. 🤓
Под капотом, в ASGI-технической спецификации, это часть [Протокола Lifespan](https://asgi.readthedocs.io/en/latest/specs/lifespan.html), и он определяет события `startup` и `shutdown`.
Под капотом, в технической спецификации ASGI, это часть [Протокола Lifespan](https://asgi.readthedocs.io/en/latest/specs/lifespan.html), и он определяет события `startup` и `shutdown`.
/// info | Информация
/// note | Примечание
Вы можете прочитать больше про обработчики `lifespan` в Starlette в [документации Starlette по Lifespan](https://www.starlette.dev/lifespan/).
@@ -162,4 +162,4 @@ async with lifespan(app):
## Подприложения { #sub-applications }
🚨 Имейте в виду, что эти события lifespan (startup и shutdown) будут выполнены только для основного приложения, а не для [Подприложения — Mounts](sub-applications.md).
🚨 Имейте в виду, что эти события lifespan (startup и shutdown) будут выполнены только для основного приложения, а не для [Подприложений - Mounts](sub-applications.md).
+3 -18
View File
@@ -20,21 +20,6 @@ FastAPI автоматически генерирует спецификации
///
## Генераторы SDK от спонсоров FastAPI { #sdk-generators-from-fastapi-sponsors }
В этом разделе представлены решения с **венчурной поддержкой** и **поддержкой компаний** от компаний, которые спонсируют FastAPI. Эти продукты предоставляют **дополнительные возможности** и **интеграции** сверх высококачественно генерируемых SDK.
Благодаря ✨ [**спонсорству FastAPI**](../help-fastapi.md#sponsor-the-author) ✨ эти компании помогают обеспечивать, чтобы фреймворк и его **экосистема** оставались здоровыми и **устойчивыми**.
Их спонсорство также демонстрирует серьёзную приверженность **сообществу** FastAPI (вам), показывая, что им важно не только предоставлять **отличный сервис**, но и поддерживать **надёжный и процветающий фреймворк** FastAPI. 🙇
Например, вы можете попробовать:
* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral)
* [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi)
Некоторые из этих решений также могут быть open source или иметь бесплатные тарифы, так что вы сможете попробовать их без финансовых затрат. Другие коммерческие генераторы SDK доступны и их можно найти онлайн. 🤓
## Создать TypeScript SDK { #create-a-typescript-sdk }
Начнём с простого приложения FastAPI:
@@ -83,7 +68,7 @@ npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client
///
Вы получите ошибки прямо в редакторе для отправляемых данных:
Вы получите ошибки прямо в редакторе кода для отправляемых данных:
<img src="/img/tutorial/generate-clients/image04.png">
@@ -186,7 +171,7 @@ FastAPI использует **уникальный ID** для каждой *о
npx @hey-api/openapi-ts -i ./openapi.json -o src/client
```
После генерации нового клиента у вас будут **чистые имена методов**, со всем **автозавершением**, **ошибками прямо в редакторе** и т.д.:
После генерации нового клиента у вас будут **чистые имена методов**, со всем **автозавершением**, **ошибками прямо в редакторе кода** и т.д.:
<img src="/img/tutorial/generate-clients/image08.png">
@@ -198,7 +183,7 @@ npx @hey-api/openapi-ts -i ./openapi.json -o src/client
* Данных запроса — в теле запроса, query‑параметрах и т.д.
* Данных ответа.
У вас также будут **ошибки прямо в редакторе** для всего.
У вас также будут **ошибки прямо в редакторе кода** для всего.
И каждый раз, когда вы обновляете код бэкенда и **перегенерируете** фронтенд, в нём появятся новые *операции пути* как методы, старые будут удалены, а любые другие изменения отразятся в сгенерированном коде. 🤓
+4 -4
View File
@@ -4,7 +4,7 @@
## Base64 и файлы { #base64-vs-files }
Сначала рассмотрите возможность использовать [Файлы в запросе](../tutorial/request-files.md) для загрузки бинарных данных и [Пользовательский HTTP-ответ — FileResponse](./custom-response.md#fileresponse--fileresponse-) для отправки бинарных данных вместо кодирования их в JSON.
Сначала рассмотрите возможность использовать [Файлы в запросе](../tutorial/request-files.md) для загрузки бинарных данных и [Пользовательский HTTP-ответ — FileResponse](./custom-response.md#fileresponse) для отправки бинарных данных вместо кодирования их в JSON.
JSON может содержать только строки в кодировке UTF-8, поэтому он не может содержать «сырые» байты.
@@ -14,7 +14,7 @@ Base64 может кодировать бинарные данные в стро
## Pydantic `bytes` { #pydantic-bytes }
Вы можете объявить Pydantic-модель с полями `bytes`, а затем использовать `val_json_bytes` в конфиге модели, чтобы указать использовать base64 для валидации входящих JSON-данных; как часть этой валидации строка base64 будет декодирована в байты.
Вы можете объявить Pydantic-модель с полями `bytes`, а затем использовать `val_json_bytes` в конфиге модели, чтобы указать использовать base64 для *валидации* входящих JSON-данных; как часть этой валидации строка base64 будет декодирована в байты.
{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *}
@@ -52,12 +52,12 @@ Base64 может кодировать бинарные данные в стро
## Pydantic `bytes` для выходных данных { #pydantic-bytes-for-output-data }
Вы также можете использовать поля `bytes` с `ser_json_bytes` в конфиге модели для выходных данных, и Pydantic будет сериализовать байты в base64 при формировании JSON-ответа.
Вы также можете использовать поля `bytes` с `ser_json_bytes` в конфиге модели для выходных данных, и Pydantic будет *сериализовать* байты в base64 при формировании JSON-ответа.
{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *}
## Pydantic `bytes` для входных и выходных данных { #pydantic-bytes-for-input-and-output-data }
И, конечно, вы можете использовать одну и ту же модель, настроенную на использование base64, чтобы обрабатывать и входящие данные (валидация) с `val_json_bytes`, и исходящие данные (сериализация) с `ser_json_bytes` при приеме и отправке JSON-данных.
И, конечно, вы можете использовать одну и ту же модель, настроенную на использование base64, чтобы обрабатывать и входящие данные (*валидировать*) с `val_json_bytes`, и исходящие данные (*сериализовать*) с `ser_json_bytes` при приеме и отправке JSON-данных.
{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *}
+12 -12
View File
@@ -1,10 +1,10 @@
# Обратные вызовы в OpenAPI { #openapi-callbacks }
Вы можете создать API с *операцией пути* (обработчиком пути), которая будет инициировать HTTP-запрос к *внешнему API*, созданному кем-то другим (скорее всего тем же разработчиком, который будет использовать ваш API).
Вы можете создать API с *операцией пути* (обработчиком пути), которая будет инициировать HTTP-запрос к *внешнему API*, созданному кем-то другим (скорее всего тем же разработчиком, который будет *использовать* ваш API).
Процесс, происходящий, когда ваше приложение API обращается к *внешнему API*, называется «callback» (обратный вызов). Программное обеспечение, написанное внешним разработчиком, отправляет HTTP-запрос вашему API, а затем ваш API выполняет обратный вызов, отправляя HTTP-запрос во *внешний API* (который, вероятно, тоже создал тот же разработчик).
Процесс, происходящий, когда ваше приложение API обращается к *внешнему API*, называется «callback» (обратный вызов). Потому что программное обеспечение, написанное внешним разработчиком, отправляет HTTP-запрос вашему API, а затем ваш API выполняет обратный вызов, отправляя HTTP-запрос во *внешний API* (который, вероятно, тоже создал тот же разработчик).
В этом случае вам может понадобиться задокументировать, как должно выглядеть это внешнее API: какую *операцию пути* оно должно иметь, какое тело запроса ожидать, какой ответ возвращать и т.д.
В этом случае вам может понадобиться задокументировать, как это внешнее API *должно* выглядеть: какую *операцию пути* оно должно иметь, какое тело запроса ожидать, какой HTTP-ответ возвращать и т.д.
## Приложение с обратными вызовами { #an-app-with-callbacks }
@@ -82,7 +82,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True})
Когда вы пишете код для документирования обратного вызова, полезно представить, что вы — тот самый *внешний разработчик*. И что вы сейчас реализуете *внешний API*, а не *свой API*.
Временное принятие этой точки зрения (внешнего разработчика) поможет интуитивно понять, куда поместить параметры, какую Pydantic-модель использовать для тела запроса, для ответа и т.д. во *внешнем API*.
Временное принятие этой точки зрения (внешнего разработчика) поможет интуитивно понять, куда поместить параметры, какую Pydantic-модель использовать для тела запроса, для HTTP-ответа и т.д. во *внешнем API*.
///
@@ -99,7 +99,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True})
Она должна выглядеть как обычная *операция пути* FastAPI:
* Вероятно, в ней должно быть объявление тела запроса, например `body: InvoiceEvent`.
* А также может быть объявление модели ответа, например `response_model=InvoiceEventReceived`.
* А также может быть объявление HTTP-ответа, который она должна возвращать, например `response_model=InvoiceEventReceived`.
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *}
@@ -124,7 +124,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True})
https://yourapi.com/invoices/?callback_url=https://www.external.org/events
```
с телом JSON:
с телом запроса JSON:
```JSON
{
@@ -140,7 +140,7 @@ https://yourapi.com/invoices/?callback_url=https://www.external.org/events
https://www.external.org/events/invoices/2expen51ve
```
с телом JSON примерно такого вида:
с телом запроса JSON примерно такого вида:
```JSON
{
@@ -149,7 +149,7 @@ https://www.external.org/events/invoices/2expen51ve
}
```
и будет ожидать от *внешнего API* ответ с телом JSON вида:
и будет ожидать от *внешнего API* HTTP-ответ с JSON в теле ответа:
```JSON
{
@@ -163,17 +163,17 @@ https://www.external.org/events/invoices/2expen51ve
///
### Подключите маршрутизатор обратного вызова { #add-the-callback-router }
### Добавьте роутер обратного вызова { #add-the-callback-router }
К этому моменту у вас есть необходимые *операции пути* обратного вызова (те, которые *внешний разработчик* должен реализовать во *внешнем API*) в созданном выше маршрутизаторе обратных вызовов.
К этому моменту у вас есть необходимые *операции пути* обратного вызова (те, которые *внешний разработчик* должен реализовать во *внешнем API*) в созданном выше роутере обратных вызовов.
Теперь используйте параметр `callbacks` в *декораторе операции пути вашего API*, чтобы передать атрибут `.routes` (это, по сути, просто `list` маршрутов/*операций пути*) из этого маршрутизатора обратных вызовов:
Теперь используйте параметр `callbacks` в *декораторе операции пути вашего API*, чтобы передать атрибут `.routes` из этого роутера обратных вызовов:
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *}
/// tip | Совет
Обратите внимание, что вы передаёте не сам маршрутизатор (`invoices_callback_router`) в `callback=`, а его атрибут `.routes`, то есть `invoices_callback_router.routes`.
Обратите внимание, что вы передаёте не сам роутер (`invoices_callback_router`) в `callbacks=`, а его атрибут `.routes`, то есть `invoices_callback_router.routes`. FastAPI будет использовать эти маршруты для генерации документации OpenAPI для обратных вызовов.
///
+2 -2
View File
@@ -22,7 +22,7 @@
Это значительно упростит вашим пользователям реализацию их API для приема ваших вебхук-запросов; возможно, они даже смогут автоматически сгенерировать часть кода своего API.
/// info | Информация
/// note | Примечание
Вебхуки доступны в OpenAPI 3.1.0 и выше, поддерживаются в FastAPI `0.99.0` и новее.
@@ -36,7 +36,7 @@
Определенные вами вебхуки попадут в схему **OpenAPI** и в автоматический **интерфейс документации**.
/// info | Информация
/// note | Примечание
Объект `app.webhooks` на самом деле — это обычный `APIRouter`, тот же тип, который вы используете при структурировании приложения по нескольким файлам.
@@ -16,17 +16,11 @@
### Использование имени *функции-обработчика пути* как operationId { #using-the-path-operation-function-name-as-the-operationid }
Если вы хотите использовать имена функций ваших API в качестве `operationId`, вы можете пройти по всем из них и переопределить `operation_id` каждой *операции пути* с помощью их `APIRoute.name`.
Если вы хотите использовать имена функций ваших API в качестве `operationId`, вы можете передать пользовательскую `generate_unique_id_function` в `FastAPI`.
Делать это следует после добавления всех *операций пути*.
Эта функция получает каждый `APIRoute` и возвращает `operationId`, который нужно использовать для этой операции пути.
{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *}
/// tip | Совет
Если вы вызываете `app.openapi()` вручную, обновите `operationId` до этого.
///
{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2,5:6,9] *}
/// warning | Предупреждение
@@ -1,6 +1,6 @@
# Response - Изменение статус-кода { #response-change-status-code }
Вы, вероятно, уже читали о том, что можно установить [статус-код ответа по умолчанию](../tutorial/response-status-code.md).
Вы, вероятно, уже читали о том, что можно установить [статус-код ответа](../tutorial/response-status-code.md) по умолчанию.
Но в некоторых случаях нужно вернуть другой статус-код, отличный от значения по умолчанию.
@@ -16,7 +16,7 @@
## Использование параметра `Response` { #use-a-response-parameter }
Вы можете объявить параметр типа `Response` в вашей *функции обработки пути* (как и для cookies и HTTP-заголовков).
Вы можете объявить параметр типа `Response` в вашей *функции-обработчике пути* (как и для cookies и HTTP-заголовков).
И затем вы можете установить `status_code` в этом *временном* объекте ответа.
@@ -1,5 +1,6 @@
# Cookies в ответе { #response-cookies }
## Использование параметра `Response` { #use-a-response-parameter }
Вы можете объявить параметр типа `Response` в вашей функции-обработчике пути.
+1 -1
View File
@@ -18,7 +18,7 @@
Вы можете возвращать `Response` или любой его подкласс.
/// info | Информация
/// note | Примечание
`JSONResponse` сам по себе является подклассом `Response`.
+6 -6
View File
@@ -2,7 +2,7 @@
## Использовать параметр `Response` { #use-a-response-parameter }
Вы можете объявить параметр типа `Response` в вашей функции-обработчике пути (как можно сделать и для cookie).
Вы можете объявить параметр типа `Response` в вашей *функции-обработчике пути* (как можно сделать и для cookie).
А затем вы можете устанавливать HTTP-заголовки в этом *временном* объекте ответа.
@@ -14,13 +14,13 @@
**FastAPI** использует этот *временный* ответ, чтобы извлечь HTTP-заголовки (а также cookie и статус-код) и поместит их в финальный HTTP-ответ, который содержит возвращённое вами значение, отфильтрованное согласно `response_model`.
Вы также можете объявлять параметр `Response` в зависимостях и устанавливать в них заголовки (и cookie).
Вы также можете объявлять параметр `Response` в зависимостях и устанавливать в них HTTP-заголовки (и cookie).
## Вернуть `Response` напрямую { #return-a-response-directly }
Вы также можете добавить HTTP-заголовки, когда возвращаете `Response` напрямую.
Создайте ответ, как описано в [Вернуть Response напрямую](response-directly.md), и передайте заголовки как дополнительный параметр:
Создайте ответ, как описано в [Вернуть Response напрямую](response-directly.md), и передайте HTTP-заголовки как дополнительный параметр:
{* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *}
@@ -30,12 +30,12 @@
**FastAPI** предоставляет те же самые `starlette.responses` как `fastapi.responses` — для вашего удобства как разработчика. Но большинство доступных классов ответов поступают напрямую из Starlette.
И поскольку `Response` часто используется для установки заголовков и cookie, **FastAPI** также предоставляет его как `fastapi.Response`.
И поскольку `Response` часто используется для установки HTTP-заголовков и cookie, **FastAPI** также предоставляет его как `fastapi.Response`.
///
## Пользовательские HTTP-заголовки { #custom-headers }
Помните, что собственные проприетарные заголовки можно добавлять, [используя префикс `X-`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers).
Помните, что собственные проприетарные HTTP-заголовки можно добавлять, [используя префикс `X-`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers).
Но если у вас есть пользовательские заголовки, которые вы хотите показывать клиенту в браузере, вам нужно добавить их в настройки CORS (подробнее см. в [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md)), используя параметр `expose_headers`, описанный в [документации Starlette по CORS](https://www.starlette.dev/middleware/#corsmiddleware).
Но если у вас есть пользовательские HTTP-заголовки, которые вы хотите показывать клиенту в браузере, вам нужно добавить их в настройки CORS (подробнее см. в [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md)), используя параметр `expose_headers`, описанный в [документации Starlette по CORS](https://www.starlette.dev/middleware/#corsmiddleware).
@@ -46,7 +46,7 @@ OAuth2 со scopes — это механизм, который использу
- `instagram_basic` используется Facebook / Instagram.
- `https://www.googleapis.com/auth/drive` используется Google.
/// info | Информация
/// note | Примечание
В OAuth2 «scope» — это просто строка, объявляющая требуемое конкретное разрешение.
@@ -76,7 +76,7 @@ OAuth2 со scopes — это механизм, который использу
Так как теперь мы объявляем эти scopes, они появятся в документации API при входе/авторизации.
И вы сможете выбрать, какие scopes вы хотите выдать доступ: `me` и `items`.
И вы сможете выбрать, для каких scopes хотите предоставить доступ: `me` и `items`.
Это тот же механизм, когда вы даёте разрешения при входе через Facebook, Google, GitHub и т.д.:
@@ -100,7 +100,7 @@ OAuth2 со scopes — это механизм, который использу
{* ../../docs_src/security/tutorial005_an_py310.py hl[157] *}
## Объявление scopes в *обработчиках путей* и зависимостях { #declare-scopes-in-path-operations-and-dependencies }
## Объявление scopes в *операциях пути* и зависимостях { #declare-scopes-in-path-operations-and-dependencies }
Теперь объявим, что операция пути для `/users/me/items/` требует scope `items`.
@@ -126,7 +126,7 @@ OAuth2 со scopes — это механизм, который использу
{* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *}
/// info | Технические детали
/// note | Технические детали
`Security` на самом деле является подклассом `Depends` и имеет всего один дополнительный параметр, который мы рассмотрим позже.
+4 -4
View File
@@ -205,7 +205,7 @@ APP_NAME="ChimichangApp"
### Создание `Settings` только один раз с помощью `lru_cache` { #creating-the-settings-only-once-with-lru-cache }
Чтение файла с диска обычно затратная (медленная) операция, поэтому, вероятно, вы захотите сделать это один раз и затем переиспользовать один и тот же объект настроек, а не читать файл при каждом запросе.
Чтение файла с диска обычно затратная (медленная) операция, поэтому, вероятно, вы захотите сделать это один раз и затем переиспользовать один и тот же объект настроек, а не читать файл при каждом HTTP-запросе.
Но каждый раз, когда мы делаем:
@@ -222,13 +222,13 @@ def get_settings():
return Settings()
```
мы бы создавали этот объект для каждого запроса и читали файл `.env` на каждый запрос. ⚠️
мы бы создавали этот объект для каждого HTTP-запроса и читали файл `.env` на каждый HTTP-запрос. ⚠️
Но так как мы используем декоратор `@lru_cache` сверху, объект `Settings` будет создан только один раз — при первом вызове. ✔️
{* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *}
Затем при любых последующих вызовах `get_settings()` в зависимостях для следующих запросов, вместо выполнения внутреннего кода `get_settings()` и создания нового объекта `Settings`, будет возвращаться тот же объект, что был возвращен при первом вызове, снова и снова.
Затем при любых последующих вызовах `get_settings()` в зависимостях для следующих HTTP-запросов, вместо выполнения внутреннего кода `get_settings()` и создания нового объекта `Settings`, будет возвращаться тот же объект, что был возвращен при первом вызове, снова и снова.
#### Технические детали `lru_cache` { #lru-cache-technical-details }
@@ -299,4 +299,4 @@ participant execute as Execute function
* Используя зависимость, вы упрощаете тестирование.
* Можно использовать файлы `.env`.
* `@lru_cache` позволяет не читать файл dotenv снова и снова для каждого запроса, при этом давая возможность переопределять его во время тестирования.
* `@lru_cache` позволяет не читать файл dotenv снова и снова для каждого HTTP-запроса, при этом давая возможность переопределять его во время тестирования.
+4 -4
View File
@@ -2,9 +2,9 @@
Если вам нужно передавать потоковые данные, которые можно представить как JSON, воспользуйтесь [стримингом JSON Lines](../tutorial/stream-json-lines.md).
Но если вы хотите передавать в потоке чистые бинарные данные или строки, ниже показано, как это сделать.
Но если вы хотите передавать в потоке **чистые бинарные данные** или строки, ниже показано, как это сделать.
/// info | Информация
/// note | Примечание
Добавлено в FastAPI 0.134.0.
@@ -40,7 +40,7 @@ FastAPI будет передавать каждый чанк данных в `S
{* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *}
Это также означает, что с `StreamingResponse` у вас есть и свобода, и ответственность — производить и кодировать байты данных ровно в том виде, в котором они должны быть отправлены, независимо от аннотаций типов. 🤓
Это также означает, что с `StreamingResponse` у вас есть и **свобода**, и **ответственность** — производить и кодировать байты данных ровно в том виде, в котором они должны быть отправлены, независимо от аннотаций типов. 🤓
### Потоковая передача байтов { #stream-bytes }
@@ -90,7 +90,7 @@ FastAPI будет передавать каждый чанк данных в `S
И во многих случаях чтение таких объектов будет блокирующей операцией (которая может заблокировать цикл событий), потому что данные читаются с диска или из сети.
/// info | Информация
/// note | Примечание
Приведённый выше пример — исключение, потому что объект `io.BytesIO` уже находится в памяти, поэтому чтение ничего не блокирует.
+1 -1
View File
@@ -81,7 +81,7 @@ http://localhost:8000/v1/agents/multivac
С этой настройкой запросы без заголовка `Content-Type` будут иметь тело запроса, обработанное как JSON — это такое же поведение, как в более старых версиях FastAPI.
/// info | Информация
/// note | Примечание
Это поведение и настройка были добавлены в FastAPI 0.132.0.
+1 -1
View File
@@ -111,7 +111,7 @@ $ fastapi dev
{* ../../docs_src/websockets_/tutorial002_an_py310.py hl[68:69,82] *}
/// info | Примечание
/// note | Примечание
В веб-сокете вызывать `HTTPException` не имеет смысла. Вместо этого нужно использовать `WebSocketException`.
+3 -3
View File
@@ -6,7 +6,7 @@
## Использование `WSGIMiddleware` { #using-wsgimiddleware }
/// info | Информация
/// note | Примечание
Для этого требуется установить `a2wsgi`, например с помощью `pip install a2wsgi`.
@@ -14,7 +14,7 @@
Нужно импортировать `WSGIMiddleware` из `a2wsgi`.
Затем оберните WSGI‑приложение (например, Flask) в middleware (Промежуточный слой).
Затем оберните WSGI‑приложение (например, Flask) в middleware (промежуточный слой).
После этого смонтируйте его на путь.
@@ -26,7 +26,7 @@
Вместо него рекомендуется использовать пакет `a2wsgi`. Использование остаётся таким же.
Просто убедитесь, что пакет `a2wsgi` установлен, и импортируйте `WSGIMiddleware` из `a2wsgi`.
Просто убедитесь, что пакет `a2wsgi` установлен, и правильно импортируйте `WSGIMiddleware` из `a2wsgi`.
///
+2 -2
View File
@@ -20,7 +20,7 @@
Он относительно тесно связан с реляционными базами данных (например, MySQL или PostgreSQL), поэтому использовать NoSQL-базу данных (например, Couchbase, MongoDB, Cassandra и т. п.) в качестве основного хранилища не очень просто.
Он был создан для генерации HTML на бэкенде, а не для создания API, используемых современным фронтендом (например, React, Vue.js и Angular) или другими системами (например, устройствами <abbr title="Internet of Things Интернет вещей">IoT</abbr>), которые с ним общаются.
Он был создан для генерации HTML на бэкенде, а не для создания API, используемых современным фронтендом (например, React, Vue.js и Angular) или другими системами (например, устройствами <abbr title="Internet of Things - Интернет вещей">IoT</abbr>), которые с ним общаются.
### [Django REST Framework](https://www.django-rest-framework.org/) { #django-rest-framework }
@@ -88,7 +88,7 @@ Requests имеет очень простой и понятный дизайн,
response = requests.get("http://example.com/some/url")
```
Соответствующая в FastAPI API-операция пути могла бы выглядеть так:
Соответствующая в FastAPI API-*операция пути* могла бы выглядеть так:
```Python hl_lines="1"
@app.get("/some/url")
+5 -5
View File
@@ -12,7 +12,7 @@
results = await some_library()
```
Тогда объявляйте *функции-обработчиков пути* с `async def`, например:
Тогда объявляйте *функции-обработчики пути* с `async def`, например:
```Python hl_lines="2"
@app.get('/')
@@ -29,7 +29,7 @@ async def read_results():
---
Если вы используете стороннюю библиотеку, которая взаимодействует с чем-то (база данных, API, файловая система и т.д.) и не поддерживает использование `await` (сейчас это относится к большинству библиотек для БД), тогда объявляйте *функции-обработчиков пути* как обычно, просто с `def`, например:
Если вы используете стороннюю библиотеку, которая взаимодействует с чем-то (база данных, API, файловая система и т.д.) и не поддерживает использование `await` (сейчас это относится к большинству библиотек для БД), тогда объявляйте *функции-обработчики пути* как обычно, просто с `def`, например:
```Python hl_lines="2"
@app.get('/')
@@ -48,7 +48,7 @@ def results():
---
**Примечание**: вы можете смешивать `def` и `async def` в *функциях-обработчиков пути* столько, сколько нужно, и объявлять каждую так, как лучше для вашего случая. FastAPI сделает с ними всё как надо.
**Примечание**: вы можете смешивать `def` и `async def` в *функциях-обработчиках пути* столько, сколько нужно, и объявлять каждую так, как лучше для вашего случая. FastAPI сделает с ними всё как надо.
В любом из случаев выше FastAPI всё равно работает асинхронно и очень быстро.
@@ -249,7 +249,7 @@ def results():
Именно такая асинхронность сделала NodeJS популярным (хотя NodeJS — не параллельный), и это сильная сторона Go как языка программирования.
Того же уровня производительности вы получаете с **FastAPI**.
Тот же уровень производительности вы получаете с **FastAPI**.
А так как можно одновременно использовать параллелизм и асинхронность, вы получаете производительность выше, чем у большинства протестированных фреймворков на NodeJS и на уровне Go, который — компилируемый язык, ближе к C [(всё благодаря Starlette)](https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1).
@@ -340,7 +340,7 @@ burgers = get_burgers(2)
---
Итак, если вы используете библиотеку, которую можно вызывать с `await`, вам нужно создать *функцию-обработчик пути*, которая её использует, с `async def`, например:
Итак, если вы используете библиотеку, которую можно вызывать с `await`, вам нужно создать *функции-обработчики пути*, которые её используют, с `async def`, например:
```Python hl_lines="2-3"
@app.get('/burgers')
+2 -2
View File
@@ -1,6 +1,6 @@
# Развертывание FastAPI у облачных провайдеров { #deploy-fastapi-on-cloud-providers }
Вы можете использовать практически любого облачного провайдера, чтобы развернуть свое приложение на FastAPI.
Вы можете использовать практически **любого облачного провайдера**, чтобы развернуть свое приложение на FastAPI.
В большинстве случаев у основных облачных провайдеров есть руководства по развертыванию FastAPI на их платформе.
@@ -16,7 +16,7 @@ FastAPI Cloud — основной спонсор и источник финан
## Облачные провайдеры — спонсоры { #cloud-providers-sponsors }
Некоторые другие облачные провайдеры ✨ [**спонсируют FastAPI**](../help-fastapi.md#sponsor-the-author) ✨ тоже. 🙇
Некоторые другие облачные провайдеры ✨ [**спонсируют FastAPI**](https://github.com/sponsors/tiangolo) ✨ тоже. 🙇
Возможно, вы захотите попробовать их сервисы и воспользоваться их руководствами:
+7 -7
View File
@@ -27,13 +27,13 @@
В [предыдущей главе про HTTPS](https.md) мы разобрались, как HTTPS обеспечивает шифрование для вашего API.
Также мы увидели, что HTTPS обычно обеспечивает компонент, **внешний** по отношению к серверу вашего приложения — **прокси-сервер TSL-терминации**.
Также мы увидели, что HTTPS обычно обеспечивает компонент, **внешний** по отношению к серверу вашего приложения — **прокси-сервер TLS-терминации**.
И должен быть компонент, отвечающий за **обновление HTTPS‑сертификатов** — это может быть тот же самый компонент или отдельный.
### Примеры инструментов для HTTPS { #example-tools-for-https }
Некоторые инструменты, которые можно использовать как прокси-сервер TSL-терминации:
Некоторые инструменты, которые можно использовать как прокси-сервер TLS-терминации:
* Traefik
* Автоматически обновляет сертификаты ✨
@@ -47,7 +47,7 @@
* С внешним компонентом (например, cert-manager) для обновления сертификатов
* Обрабатывается внутри облачного провайдера как часть его услуг (см. ниже 👇)
Другой вариант — использовать **облачный сервис**, который возьмёт на себя больше задач, включая настройку HTTPS. Там могут быть ограничения или дополнительная стоимость и т.п., но в таком случае вам не придётся самим настраивать прокси-сервер TSL-терминации.
Другой вариант — использовать **облачный сервис**, который возьмёт на себя больше задач, включая настройку HTTPS. Там могут быть ограничения или дополнительная стоимость и т.п., но в таком случае вам не придётся самим настраивать прокси-сервер TLS-терминации.
В следующих главах я покажу конкретные примеры.
@@ -243,7 +243,7 @@
Не беспокойтесь, если некоторые пункты про **контейнеры**, Docker или Kubernetes пока кажутся неочевидными.
Я расскажу больше про образы контейнеров, Docker, Kubernetes и т.п. в следующей главе: [FastAPI внутри контейнеров — Docker](docker.md).
Я расскажу больше про образы контейнеров, Docker, Kubernetes и т.п. в одной из будущих глав: [FastAPI внутри контейнеров — Docker](docker.md).
///
@@ -281,7 +281,7 @@
/// tip | Совет
Я приведу более конкретные примеры с контейнерами в следующей главе: [FastAPI внутри контейнеров — Docker](docker.md).
Я приведу более конкретные примеры с контейнерами в одной из будущих глав: [FastAPI внутри контейнеров — Docker](docker.md).
///
@@ -301,9 +301,9 @@
Также возможен **всплеск** использования вашего API: он мог «взорваться» по популярности, или какие‑то сервисы/боты начали его активно использовать. На такие случаи стоит иметь запас ресурсов.
Можно задать **целевое значение**, например **между 50% и 90%** использования ресурсов. Скорее всего, именно эти вещи вы будете измерять и на их основе настраивать развёртывание.
Можно задать **произвольное число** в качестве цели, например **между 50% и 90%** использования ресурсов. Скорее всего, именно эти вещи вы будете измерять и на их основе настраивать развёртывание.
Можно использовать простые инструменты вроде `htop`, чтобы смотреть загрузку CPU и RAM на сервере или по процессам. Или более сложные распределённые системы мониторинга.
Можно использовать простые инструменты вроде `htop`, чтобы смотреть загрузку CPU и RAM на сервере или по процессам. Или более сложные инструменты мониторинга, которые могут быть распределены по серверам и т.п.
## Резюме { #recap }
+13 -13
View File
@@ -132,7 +132,7 @@ Successfully installed fastapi pydantic
</div>
/// info | Информация
/// note | Заметка
Существуют и другие форматы и инструменты для описания и установки зависимостей.
@@ -273,9 +273,9 @@ CMD fastapi run app/main.py --port 80
└── requirements.txt
```
#### За прокси-сервером TSL-терминации { #behind-a-tls-termination-proxy }
#### За прокси-сервером TLS-терминации { #behind-a-tls-termination-proxy }
Если вы запускаете контейнер за прокси-сервером TSL-терминации (балансировщиком нагрузки), таким как Nginx или Traefik, добавьте опцию `--proxy-headers`. Это сообщит Uvicorn (через FastAPI CLI), что приложение работает за HTTPS и можно доверять соответствующим заголовкам.
Если вы запускаете контейнер за прокси-сервером TLS-терминации (балансировщиком нагрузки), таким как Nginx или Traefik, добавьте опцию `--proxy-headers`. Это сообщит Uvicorn (через FastAPI CLI), что можно доверять заголовкам, отправленным этим прокси и сообщающим, что приложение работает за HTTPS, и т.д.
```Dockerfile
CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"]
@@ -407,9 +407,9 @@ CMD ["fastapi", "run", "main.py", "--port", "80"]
1. Копируем файл `main.py` напрямую в `/code` (без директории `./app`).
2. Используем `fastapi run` для запуска приложения из одного файла `main.py`.
2. Используем `fastapi run`, чтобы «отдавать» приложение из одного файла `main.py`.
Когда вы передаёте файл в `fastapi run`, он автоматически определит, что это одиночный файл, а не часть пакета, и поймёт, как его импортировать и запустить ваше FastAPI-приложение. 😎
Когда вы передаёте файл в `fastapi run`, он автоматически определит, что это одиночный файл, а не часть пакета, и поймёт, как импортировать и «отдавать» ваше FastAPI-приложение. 😎
## Концепции развертывания { #deployment-concepts }
@@ -462,17 +462,17 @@ CMD ["fastapi", "run", "main.py", "--port", "80"]
### Балансировщик нагрузки { #load-balancer }
При использовании контейнеров обычно есть компонент, **слушающий главный порт**. Это может быть другой контейнер — **прокси-сервер TSL-терминации** для обработки **HTTPS** или похожий инструмент.
При использовании контейнеров обычно есть компонент, **слушающий главный порт**. Это может быть другой контейнер — **прокси-сервер TLS-терминации** для обработки **HTTPS** или похожий инструмент.
Поскольку этот компонент принимает **нагрузку** запросов и распределяет её между воркерами **сбалансированно**, его часто называют **балансировщиком нагрузки**.
/// tip | Подсказка
Тот же компонент **прокси-сервер TSL-терминации**, который обрабатывает HTTPS, скорее всего также будет **балансировщиком нагрузки**.
Тот же компонент **прокси-сервер TLS-терминации**, который обрабатывает HTTPS, скорее всего также будет **балансировщиком нагрузки**.
///
При работе с контейнерами система, которую вы используете для запуска и управления ими, уже имеет внутренние средства для передачи **сетевого взаимодействия** (например, HTTP-запросов) от **балансировщика нагрузки** (который также может быть **прокси-сервером TSL-терминации**) к контейнеру(-ам) с вашим приложением.
При работе с контейнерами система, которую вы используете для запуска и управления ими, уже имеет внутренние средства для передачи **сетевого взаимодействия** (например, HTTP-запросов) от **балансировщика нагрузки** (который также может быть **прокси-сервером TLS-терминации**) к контейнеру(-ам) с вашим приложением.
### Один балансировщик — несколько контейнеров-воркеров { #one-load-balancer-multiple-worker-containers }
@@ -525,7 +525,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"]
Вы можете развёртывать на **одном сервере** (не кластере) с **Docker Compose**, и у вас не будет простого способа управлять репликацией контейнеров (в Docker Compose), сохраняя общую сеть и **балансировку нагрузки**.
Тогда вы можете захотеть **один контейнер** с **менеджером процессов**, который запускает **несколько воркеров** внутри.
Тогда вы можете захотеть **один контейнер** с **менеджером процессов**, который запускает **несколько воркер-процессов** внутри.
---
@@ -556,7 +556,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"]
Если у вас **несколько контейнеров**, и, вероятно, каждый запускает **один процесс** (например, в кластере **Kubernetes**), то вы, скорее всего, захотите иметь **отдельный контейнер**, выполняющий **предварительные шаги** в одном контейнере и одном процессе **до** запуска реплицированных контейнеров-воркеров.
/// info | Информация
/// note | Заметка
Если вы используете Kubernetes, это, вероятно, будет [Init Container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/).
@@ -566,7 +566,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"]
### Один контейнер { #single-container }
Если у вас простая схема с **одним контейнером**, который затем запускает несколько **воркеров** (или один процесс), можно выполнить подготовительные шаги в этом же контейнере непосредственно перед запуском процесса с приложением.
Если у вас простая схема с **одним контейнером**, который затем запускает несколько **воркер-процессов** (или один процесс), можно выполнить подготовительные шаги в этом же контейнере непосредственно перед запуском процесса с приложением.
### Базовый Docker-образ { #base-docker-image }
@@ -580,7 +580,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"]
/// note | Технические подробности
Этот Docker-образ был создан в то время, когда Uvicorn не умел управлять и перезапускать «упавших» воркеров, и приходилось использовать Gunicorn вместе с Uvicorn, что добавляло заметную сложность, лишь бы Gunicorn управлял и перезапускал воркеров Uvicorn.
Этот Docker-образ был создан в то время, когда Uvicorn не умел управлять и перезапускать «упавших» воркеров, и приходилось использовать Gunicorn вместе с Uvicorn, что добавляло заметную сложность, лишь бы Gunicorn управлял и перезапускал воркер-процессы Uvicorn.
Но теперь, когда Uvicorn (и команда `fastapi`) поддерживают `--workers`, нет причин использовать базовый Docker-образ вместо сборки своего (кода получается примерно столько же 😅).
@@ -615,4 +615,4 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"]
В большинстве случаев вы, вероятно, не захотите использовать какой-либо базовый образ, а вместо этого **соберёте образ контейнера с нуля** на основе официального Docker-образа Python.
Заботясь о **порядке** инструкций в `Dockerfile` и используя **кэш Docker**, вы можете **минимизировать время сборки**, чтобы повысить продуктивность (и не скучать). 😎
Заботясь о **порядке** инструкций в `Dockerfile` и используя **кэш Docker**, вы можете **минимизировать время сборки**, чтобы повысить продуктивность (и не скучать). 😎
+3 -21
View File
@@ -1,26 +1,6 @@
# FastAPI Cloud { #fastapi-cloud }
Вы можете развернуть своё приложение FastAPI в [FastAPI Cloud](https://fastapicloud.com) одной командой, присоединяйтесь к списку ожидания, если ещё не сделали этого. 🚀
## Вход { #login }
Убедитесь, что у вас уже есть аккаунт **FastAPI Cloud** (мы пригласили вас из списка ожидания 😉).
Затем выполните вход:
<div class="termy">
```console
$ fastapi login
You are logged in to FastAPI Cloud 🚀
```
</div>
## Деплой { #deploy }
Теперь разверните приложение одной командой:
Вы можете развернуть своё приложение FastAPI в [FastAPI Cloud](https://fastapicloud.com) всего **одной командой**. 🚀
<div class="termy">
@@ -36,6 +16,8 @@ Deploying to FastAPI Cloud...
</div>
CLI автоматически определит ваше приложение FastAPI и развернёт его в облаке. Если вы не вошли в аккаунт, откроется браузер для завершения процесса аутентификации.
Вот и всё! Теперь вы можете открыть своё приложение по этому URL. ✨
## О FastAPI Cloud { #about-fastapi-cloud }
+4 -4
View File
@@ -6,7 +6,7 @@
/// tip | Совет
Если вы торопитесь или вам это не важно, переходите к следующим разделам с пошаговыми инструкциями по настройке всего разными способами.
Если вы торопитесь или вам это не важно, продолжайте со следующих разделов с пошаговыми инструкциями по настройке всего разными способами.
///
@@ -65,7 +65,7 @@
Чаще всего всё начинается с **приобретения** **имени домена**. Затем вы настраиваете его на DNS‑сервере (возможно, у того же облачного провайдера).
Скорее всего, вы получите облачный сервер (виртуальную машину) или что-то подобное, и у него будет <dfn title="Со временем не меняется. Не динамический.">постоянный</dfn> **публичный IP-адрес**.
Скорее всего, вы получите облачный сервер (виртуальную машину) или что-то подобное, и у него будет <dfn title="Не меняется со временем. Не динамический.">постоянный</dfn> **публичный IP-адрес**.
На DNS‑сервере(ах) вы настроите запись («`A record`» - запись типа A), указывающую, что **ваш домен** должен указывать на публичный **IP‑адрес вашего сервера**.
@@ -194,7 +194,7 @@ DNS‑серверы ответят браузеру, какой **конкре
Когда вы используете прокси для обработки HTTPS, ваш **сервер приложения** (например, Uvicorn через FastAPI CLI) ничего не знает о процессе HTTPS, он общается обычным HTTP с **прокси‑сервером TLS-терминации**.
Обычно этот **прокси** на лету добавляет некоторые HTTP‑заголовки перед тем, как переслать запрос на **сервер приложения**, чтобы тот знал, что запрос был **проксирован**.
Обычно этот **прокси** на лету добавляет некоторые HTTP‑заголовки перед тем, как переслать запрос на **сервер приложения**, чтобы тот знал, что запрос был **переслан** прокси.
/// note | Технические детали
@@ -218,7 +218,7 @@ DNS‑серверы ответят браузеру, какой **конкре
/// tip | Совет
Подробнее об этом вы можете узнать в документации: [За прокси — Включить пересылаемые заголовки прокси](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers)
Подробнее об этом вы можете узнать в документации: [За прокси — включить пересылаемые заголовки прокси](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers)
///
+2 -3
View File
@@ -2,7 +2,7 @@
## Используйте команду `fastapi run` { #use-the-fastapi-run-command }
Коротко: используйте `fastapi run`, чтобы запустить ваше приложение FastAPI:
Коротко: используйте `fastapi run`, чтобы предоставлять доступ к вашему приложению FastAPI:
<div class="termy">
@@ -46,7 +46,7 @@ $ <font color="#4E9A06">fastapi</font> run <u style="text-decoration-style:solid
Давайте немного углубимся в детали.
FastAPI использует стандарт для построения Python‑веб‑фреймворков и серверов под названием <abbr title="Asynchronous Server Gateway Interface Асинхронный шлюзовый интерфейс сервера">ASGI</abbr>. FastAPI — ASGI-веб‑фреймворк.
FastAPI использует стандарт для построения Python‑веб‑фреймворков и серверов под названием <abbr title="Asynchronous Server Gateway Interface - Асинхронный шлюзовый интерфейс сервера">ASGI</abbr>. FastAPI — ASGI-веб‑фреймворк.
Главное, что вам нужно, чтобы запустить приложение **FastAPI** (или любое другое ASGI‑приложение) на удалённой серверной машине, — это программа ASGI‑сервера, такая как **Uvicorn**; именно он используется по умолчанию в команде `fastapi`.
@@ -56,7 +56,6 @@ FastAPI использует стандарт для построения Python
* [Hypercorn](https://hypercorn.readthedocs.io/): ASGI‑сервер, среди прочего совместимый с HTTP/2 и Trio.
* [Daphne](https://github.com/django/daphne): ASGI‑сервер, созданный для Django Channels.
* [Granian](https://github.com/emmett-framework/granian): HTTP‑сервер на Rust для Python‑приложений.
* [NGINX Unit](https://unit.nginx.org/howto/fastapi/): NGINX Unit — лёгкая и многофункциональная среда выполнения веб‑приложений.
## Сервер как машина и сервер как программа { #server-machine-and-server-program }
+1 -1
View File
@@ -17,7 +17,7 @@
Здесь я покажу, как использовать **Uvicorn** с **воркер-процессами** через команду `fastapi` или напрямую через команду `uvicorn`.
/// info | Информация
/// note | Примечание
Если вы используете контейнеры, например Docker или Kubernetes, я расскажу об этом подробнее в следующей главе: [FastAPI в контейнерах — Docker](docker.md).
+1 -1
View File
@@ -20,4 +20,4 @@
- **Развернуть в FastAPI Cloud** — развертывание вашего приложения в один клик в [FastAPI Cloud](https://fastapicloud.com/).
- **Поток логов приложения** — потоковая передача логов в реальном времени из вашего приложения, развернутого в FastAPI Cloud, с фильтрацией по уровню и текстовым поиском.
Если вы хотите поверхностно ознакомиться с возможностями расширения, откройте палитру команд (<kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd> или на macOS: <kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd>), выберите «Welcome: Open walkthrough...», а затем «Get started with FastAPI».
Если вы хотите ознакомиться с возможностями расширения, вы можете посмотреть walkthrough расширения, открыв палитру команд (<kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd> или на macOS: <kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd>) и выбрав «Welcome: Open walkthrough...», а затем walkthrough «Get started with FastAPI».
+8 -8
View File
@@ -50,9 +50,9 @@ Hello Wade Wilson
////
## Чтение переменных окружения в python { #read-env-vars-in-python }
## Чтение переменных окружения в Python { #read-env-vars-in-python }
Так же существует возможность создания переменных окружения **вне** Python, в терминале (или любым другим способом), а затем **чтения их в Python**.
Также существует возможность создания переменных окружения **вне** Python, в терминале (или любым другим способом), а затем **чтения их в Python**.
Например, у вас есть файл `main.py`:
@@ -67,7 +67,7 @@ print(f"Hello {name} from Python")
Второй аргумент [`os.getenv()`](https://docs.python.org/3.8/library/os.html#os.getenv) - это возвращаемое по умолчанию значение.
Если значение не указано, то по умолчанию оно равно `None`. В данном случае мы указываем `«World»` в качестве значения по умолчанию.
Если значение не указано, то по умолчанию оно равно `None`. В данном случае мы указываем `"World"` в качестве значения по умолчанию.
///
@@ -157,13 +157,13 @@ Hello World from Python
///
## Типизация и Валидация { #types-and-validation }
## Типы и валидация { #types-and-validation }
Эти переменные окружения могут работать только с **текстовыми строками**, поскольку они являются внешними по отношению к Python и должны быть совместимы с другими программами и остальной системой (и даже с различными операционными системами, такими как Linux, Windows, macOS).
Это означает, что **любое значение**, считанное в Python из переменной окружения, **будет `str`**, и любое преобразование к другому типу или любая валидация должны быть выполнены в коде.
Подробнее об использовании переменных окружения для работы с **настройками приложения** вы узнаете в [Расширенное руководство пользователя - Настройки и переменные среды](./advanced/settings.md).
Подробнее об использовании переменных окружения для работы с **настройками приложения** вы узнаете в [Расширенном руководстве пользователя - Настройки и переменные окружения](./advanced/settings.md).
## Переменная окружения `PATH` { #path-environment-variable }
@@ -285,14 +285,14 @@ $ C:\opt\custompython\bin\python
////
Эта информация будет полезна при изучении [Виртуальных окружений](virtual-environments.md).
Эта информация будет полезна при изучении [виртуальных окружений](virtual-environments.md).
## Вывод { #conclusion }
Благодаря этому вы должны иметь базовое представление о том, что такое **переменные окружения** и как использовать их в Python.
Подробнее о них вы также можете прочитать в [статье о переменных окружения на википедии](https://en.wikipedia.org/wiki/Environment_variable).
Подробнее о них вы также можете прочитать в [статье о переменных окружения на Википедии](https://en.wikipedia.org/wiki/Environment_variable).
Во многих случаях не всегда очевидно, как переменные окружения могут быть полезны и применимы. Но они постоянно появляются в различных сценариях разработки, поэтому знать о них полезно.
Например, эта информация понадобится вам в следующем разделе, посвященном [Виртуальным окружениям](virtual-environments.md).
Например, эта информация понадобится вам в следующем разделе, посвященном [виртуальным окружениям](virtual-environments.md).
+11 -11
View File
@@ -17,7 +17,7 @@
* [**Swagger UI**](https://github.com/swagger-api/swagger-ui), с интерактивным исследованием, вызовом и тестированием вашего API прямо из браузера.
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
![Взаимодействие со Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
* Альтернативная документация API в [**ReDoc**](https://github.com/Rebilly/ReDoc).
@@ -36,7 +36,7 @@ from datetime import date
from pydantic import BaseModel
# Объявляем параметр как `str`
# Объявляем переменную как `str`
# и получаем поддержку редактора кода внутри функции
def main(user_id: str):
return user_id
@@ -71,9 +71,9 @@ my_second_user: User = User(**second_user_data)
///
### Поддержка редакторов { #editor-support }
### Поддержка редакторов кода { #editor-support }
Весь фреймворк был продуман так, чтобы быть простым и интуитивно понятным в использовании, все решения были проверены на множестве редакторов еще до начала разработки, чтобы обеспечить наилучшие условия при написании кода.
Весь фреймворк был продуман так, чтобы быть простым и интуитивно понятным в использовании, все решения были проверены на множестве редакторов кода еще до начала разработки, чтобы обеспечить наилучшие условия при написании кода.
В опросах Python‑разработчиков видно, [что одной из самых часто используемых функций является «автозавершение»](https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features).
@@ -81,15 +81,15 @@ my_second_user: User = User(**second_user_data)
Вам редко нужно будет возвращаться к документации.
Вот как ваш редактор может вам помочь:
Вот как ваш редактор кода может вам помочь:
* в [Visual Studio Code](https://code.visualstudio.com/):
![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)
![поддержка редактора кода](https://fastapi.tiangolo.com/img/vscode-completion.png)
* в [PyCharm](https://www.jetbrains.com/pycharm/):
![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png)
![поддержка редактора кода](https://fastapi.tiangolo.com/img/pycharm-completion.png)
Вы будете получать автозавершение кода даже там, где вы считали это невозможным раньше. Как пример, ключ `price` внутри тела JSON (который может быть вложенным), приходящего в запросе.
@@ -151,11 +151,11 @@ FastAPI включает в себя чрезвычайно простую в и
Любая интеграция разработана настолько простой в использовании (с зависимостями), что вы можете создать «плагин» для своего приложения в пару строк кода, используя ту же структуру и синтаксис, что и для ваших *операций пути*.
### Проверен { #tested }
### Протестирован { #tested }
* 100% <dfn title="Количество автоматически проверяемого кода">покрытие тестами</dfn>.
* 100% <dfn title="Количество автоматически протестированного кода">покрытие тестами</dfn>.
* 100% <dfn title="Аннотации типов Python, благодаря которым ваш редактор кода и внешние инструменты могут обеспечить вам лучшую поддержку">аннотирование типов</dfn> в кодовой базе.
* Используется в продакшн‑приложениях.
* Используется в приложениях в продакшн.
## Возможности Starlette { #starlette-features }
@@ -190,7 +190,7 @@ FastAPI включает в себя чрезвычайно простую в и
* **Никакой нервотрёпки**:
* Не нужно изучать новые схемы в микроязыках.
* Если вы знаете типы в Python, вы знаете, как использовать Pydantic.
* Прекрасно сочетается с вашим **<abbr title="Integrated Development Environment - Интегрированная среда разработки: похоже на редактор кода">IDE</abbr>/<dfn title="Программа, которая проверяет код на ошибки">линтер</dfn>/мозгом**:
* Прекрасно сочетается с вашим **<abbr title="Integrated Development Environment - Интегрированная среда разработки: похожая на редактор кода">IDE</abbr>/<dfn title="Программа, которая проверяет код на ошибки">линтер</dfn>/мозгом**:
* Потому что структуры данных pydantic — это всего лишь экземпляры классов, определённых вами; автозавершение, проверка кода, mypy и ваша интуиция — всё будет работать с вашими валидированными данными.
* Валидация **сложных структур**:
* Использование иерархических моделей Pydantic; `List`, `Dict` и т.п. из модуля `typing`.
+1 -1
View File
@@ -38,7 +38,7 @@
## Подписаться на автора { #follow-the-author }
Вы можете подписаться на [меня (Sebastián Ramírez / `tiangolo`)](https://tiangolo.com) в нескольких местах, чтобы узнавать новости о FastAPI и друзьях:
Вы можете подписаться на [меня (Sebastián Ramírez / `tiangolo`)](https://tiangolo.com), автора, в нескольких местах, чтобы узнавать новости о FastAPI и друзьях:
* [@tiangolo в **GitHub**](https://github.com/tiangolo).
* [@tiangolo в **X (Twitter)**](https://x.com/tiangolo)
+1 -1
View File
@@ -26,7 +26,7 @@ FastAPI преобразует эти настройки в **JSON**, чтобы
## Изменить тему { #change-the-theme }
Аналогично вы можете задать тему подсветки синтаксиса с ключом "syntaxHighlight.theme" (обратите внимание, что посередине стоит точка):
Аналогично вы можете задать тему подсветки синтаксиса с ключом `"syntaxHighlight.theme"` (обратите внимание, что посередине стоит точка):
{* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *}
@@ -18,13 +18,13 @@
Некоторые сценарии:
* Преобразование тел запросов, не в формате JSON, в JSON (например, [`msgpack`](https://msgpack.org/index.html)).
* Преобразование тел запросов не в формате JSON в JSON (например, [`msgpack`](https://msgpack.org/index.html)).
* Распаковка тел запросов, сжатых с помощью gzip.
* Автоматическое логирование всех тел запросов.
## Обработка пользовательского кодирования тела запроса { #handling-custom-request-body-encodings }
Посмотрим как использовать пользовательский подкласс `Request` для распаковки gzip-запросов.
Посмотрим, как использовать пользовательский подкласс `Request` для распаковки gzip-запросов.
И подкласс `APIRoute`, чтобы использовать этот пользовательский класс запроса.
@@ -38,9 +38,9 @@
Сначала создадим класс `GzipRequest`, который переопределит метод `Request.body()` и распакует тело запроса при наличии соответствующего HTTP-заголовка.
Если в заголовке нет `gzip`, он не будет пытаться распаковывать тело.
Если в HTTP-заголовке нет `gzip`, он не будет пытаться распаковывать тело.
Таким образом, один и тот же класс маршрута сможет обрабатывать как gzip-сжатые, так и несжатые запросы.
Таким образом, один и тот же класс маршрута сможет обрабатывать как gzip-сжатые, так и несжатые HTTP-запросы.
{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[9:16] *}
@@ -90,7 +90,7 @@
Тем же подходом можно воспользоваться, чтобы получить доступ к телу запроса в обработчике исключений.
Нужно лишь обработать запрос внутри блока `try`/`except`:
Нужно лишь обработать HTTP-запрос внутри блока `try`/`except`:
{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[14,16] *}
@@ -104,6 +104,6 @@
{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[26] *}
В этом примере *операции пути*, объявленные в `router`, будут использовать пользовательский класс `TimedRoute` и получат дополнительный HTTP-заголовок `X-Response-Time` в ответе с временем, затраченным на формирование ответа:
В этом примере *операции пути*, объявленные в `router`, будут использовать пользовательский класс `TimedRoute` и получат дополнительный HTTP-заголовок `X-Response-Time` в HTTP-ответе с временем, затраченным на формирование HTTP-ответа:
{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[13:20] *}
+11 -3
View File
@@ -25,11 +25,19 @@
* `openapi_version`: Версия используемой спецификации OpenAPI. По умолчанию — последняя: `3.1.0`.
* `summary`: Краткое описание API.
* `description`: Описание вашего API; может включать Markdown и будет отображаться в документации.
* `routes`: Список маршрутов — это каждая зарегистрированная *операция пути*. Берутся из `app.routes`.
* `routes`: Список маршрутов — это каждая зарегистрированная *операция пути*. Берутся из `app.routes`. FastAPI использует их, чтобы собрать зарегистрированные *операции пути*, включая те из подключённых роутеров.
/// info | Информация
/// tip | Технические детали
Параметр `summary` доступен в OpenAPI 3.1.0 и выше, поддерживается FastAPI версии 0.99.0 и выше.
`app.routes` — это более низкоуровневое дерево маршрутов. Оно может включать кандидаты маршрутов, которые FastAPI использует внутренне для подключённых роутеров, а не только конечные объекты `APIRoute`.
Вы всё равно можете передать `app.routes` в `get_openapi()`. FastAPI обойдёт это дерево маршрутов, чтобы собрать фактические операции пути.
///
/// note | Примечание
Параметр `summary` доступен в OpenAPI 3.1.0 и выше, поддерживается FastAPI 0.99.0 и выше.
///
+1
View File
@@ -1,5 +1,6 @@
# GraphQL { #graphql }
Так как **FastAPI** основан на стандарте **ASGI**, очень легко интегрировать любую библиотеку **GraphQL**, также совместимую с ASGI.
Вы можете комбинировать обычные *операции пути* FastAPI с GraphQL в одном приложении.
@@ -8,6 +8,8 @@ FastAPI версии 0.119.0 добавил частичную поддержк
FastAPI 0.126.0 убрал поддержку Pydantic v1, при этом ещё некоторое время продолжал поддерживать `pydantic.v1`.
FastAPI 0.128.0 также убрал поддержку `pydantic.v1`, так что последние версии FastAPI требуют Pydantic v2.
/// warning | Предупреждение
Команда Pydantic прекратила поддержку Pydantic v1 для последних версий Python, начиная с **Python 3.14**.
@@ -54,6 +56,16 @@ Pydantic v2 включает всё из Pydantic v1 как подмодуль `
### Поддержка FastAPI для Pydantic v1 внутри v2 { #fastapi-support-for-pydantic-v1-in-v2 }
/// warning | Предупреждение
Эта поддержка FastAPI для моделей `pydantic.v1` была добавлена в **FastAPI 0.119.0** и удалена в **FastAPI 0.128.0**. Она задумывалась как временная помощь при миграции на Pydantic v2.
В текущих версиях FastAPI использование модели `pydantic.v1` в вашем приложении вызовет ошибку.
Остальная часть этого раздела описывает временную поддержку, доступную только в этих старых версиях.
///
Начиная с FastAPI 0.119.0, есть также частичная поддержка Pydantic v1 изнутри Pydantic v2, чтобы упростить миграцию на v2.
Таким образом, вы можете обновить Pydantic до последней версии 2 и сменить импорты на подмодуль `pydantic.v1` — во многих случаях всё просто заработает.
@@ -122,6 +134,12 @@ graph TB
### Мигрируйте по шагам { #migrate-in-steps }
/// warning | Предупреждение
Постепенная миграция с использованием моделей Pydantic v1 и v2 в одном приложении, описанная ниже, работает только в **FastAPI 0.119.0 до 0.127.x**. Она была удалена в **FastAPI 0.128.0**, последние версии требуют модели **Pydantic v2**.
///
/// tip | Совет
Сначала попробуйте `bump-pydantic`: если тесты проходят и всё работает, вы справились одной командой. ✨
@@ -1,6 +1,6 @@
# Разделять схемы OpenAPI для входа и выхода или нет { #separate-openapi-schemas-for-input-and-output-or-not }
При использовании **Pydantic v2** сгенерированный OpenAPI становится чуть более точным и **корректным**, чем раньше. 😎
С момента выхода **Pydantic v2** сгенерированный OpenAPI становится чуть более точным и **корректным**, чем раньше. 😎
На самом деле, в некоторых случаях в OpenAPI будет даже **две JSON-схемы** для одной и той же Pydantic‑модели: для входа и для выхода — в зависимости от наличия **значений по умолчанию**.
@@ -85,7 +85,7 @@
В таком случае вы можете отключить эту функциональность в **FastAPI** с помощью параметра `separate_input_output_schemas=False`.
/// info | Информация
/// note | Примечание
Поддержка `separate_input_output_schemas` появилась в FastAPI `0.102.0`. 🤓
+10 -10
View File
@@ -57,7 +57,7 @@ FastAPI — это современный, быстрый (высокопрои
<!-- sponsors -->
### Ключевой-спонсор { #keystone-sponsor }
### Ключевой спонсор { #keystone-sponsor }
<div class="fastapi-sponsors fastapi-sponsors--keystone">
{% for sponsor in sponsors.keystone -%}
@@ -161,7 +161,7 @@ FastAPI — это современный, быстрый (высокопрои
В конце 2025 года вышел [мини-документальный фильм о FastAPI](https://www.youtube.com/watch?v=mpR8ngthqiE), вы можете посмотреть его онлайн:
<a class="fastapi-feature-banner" href="https://www.youtube.com/watch?v=mpR8ngthqiE"><img src="https://fastapi.tiangolo.com/img/fastapi-documentary.jpg" alt="FastAPI Mini Documentary"></a>
<a class="fastapi-feature-banner" href="https://www.youtube.com/watch?v=mpR8ngthqiE"><img src="https://fastapi.tiangolo.com/img/fastapi-documentary.jpg" alt="Мини-документальный фильм о FastAPI"></a>
## **Typer**, FastAPI для CLI { #typer-the-fastapi-of-clis }
@@ -364,11 +364,11 @@ def update_item(item_id: int, item: Item):
* Нажмите кнопку «Try it out», это позволит вам заполнить параметры и напрямую взаимодействовать с API:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png)
![Взаимодействие со Swagger UI](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png)
* Затем нажмите кнопку «Execute», интерфейс свяжется с вашим API, отправит параметры, получит результаты и отобразит их на экране:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png)
![Взаимодействие со Swagger UI](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png)
### Обновление альтернативной документации API { #alternative-api-docs-upgrade }
@@ -471,7 +471,7 @@ item: Item
...и посмотрите, как ваш редактор кода будет автоматически дополнять атрибуты и знать их типы:
![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)
![Поддержка редактора кода](https://fastapi.tiangolo.com/img/vscode-completion.png)
Более полный пример с дополнительными возможностями см. в <a href="https://fastapi.tiangolo.com/ru/tutorial/">Учебник - Руководство пользователя</a>.
@@ -492,9 +492,7 @@ item: Item
### Разверните приложение (опционально) { #deploy-your-app-optional }
При желании вы можете развернуть своё приложение FastAPI в [FastAPI Cloud](https://fastapicloud.com), присоединяйтесь к списку ожидания, если ещё не сделали этого. 🚀
Если у вас уже есть аккаунт **FastAPI Cloud** (мы пригласили вас из списка ожидания 😉), вы можете развернуть ваше приложение одной командой.
При желании вы можете развернуть своё приложение FastAPI в [FastAPI Cloud](https://fastapicloud.com) одной командой. 🚀
<div class="termy">
@@ -510,6 +508,8 @@ Deploying to FastAPI Cloud...
</div>
CLI автоматически определит ваше приложение FastAPI и развернёт его в облаке. Если вы не вошли в систему, откроется браузер для завершения процесса аутентификации.
Вот и всё! Теперь вы можете открыть ваше приложение по этой ссылке. ✨
#### О FastAPI Cloud { #about-fastapi-cloud }
@@ -524,7 +524,7 @@ FastAPI Cloud — основной спонсор и источник финан
#### Развертывание у других облачных провайдеров { #deploy-to-other-cloud-providers }
FastAPI — это open source и стандартизированный фреймворк. Вы можете развернуть приложения FastAPI у любого облачного провайдера на ваш выбор.
FastAPI — это проект с открытым исходным кодом, основанный на стандартах. Вы можете развернуть приложения FastAPI у любого облачного провайдера на ваш выбор.
Следуйте руководствам вашего облачного провайдера по развертыванию приложений FastAPI. 🤓
@@ -544,7 +544,7 @@ FastAPI зависит от Pydantic и Starlette.
Используется Pydantic:
* [`email-validator`](https://github.com/JoshData/python-email-validator) — для проверки адресов электронной почты.
* [`email-validator`](https://github.com/JoshData/python-email-validator) — для валидации адресов электронной почты.
Используется Starlette:
+2 -2
View File
@@ -20,9 +20,9 @@
- 🦇 Поддержка тёмной темы.
- 🐋 [Docker Compose](https://www.docker.com) для разработки и продакшн.
- 🔒 Безопасное хэширование паролей по умолчанию.
- 🔑 Аутентификация по JWT‑токенам.
- 🔑 Аутентификация JWT (JSON Web Token).
- 📫 Восстановление пароля по электронной почте.
- ✅ Тесты с [Pytest](https://pytest.org).
- 📞 [Traefik](https://traefik.io) в роли обратного прокси / балансировщика нагрузки.
- 🚢 Инструкции по развёртыванию с использованием Docker Compose, включая настройку фронтенд‑прокси Traefik для автоматического получения сертификатов HTTPS.
- 🏭 CI (continuous integration) и CD (continuous deployment) на основе GitHub Actions.
- 🏭 CI (непрерывная интеграция) и CD (непрерывное развертывание) на основе GitHub Actions.
+15 -15
View File
@@ -1,20 +1,20 @@
# Введение в типы Python { #python-types-intro }
Python поддерживает необязательные «подсказки типов» (их также называют «аннотациями типов»).
Python поддерживает необязательные «аннотации типов» (также называемые «подсказками типов»).
Эти **«подсказки типов»** или аннотации — это специальный синтаксис, позволяющий объявлять <dfn title="например: str, int, float, bool">тип</dfn> переменной.
Эти **«аннотации типов»**, или просто аннотации, — это специальный синтаксис, позволяющий объявлять <dfn title="например: str, int, float, bool">тип</dfn> переменной.
Объявляя типы для ваших переменных, редакторы кода и инструменты смогут лучше вас поддерживать.
Это всего лишь **краткое руководство / напоминание** о подсказках типов в Python. Оно охватывает только минимум, необходимый для их использования с **FastAPI**... что на самом деле очень мало.
Это всего лишь **краткое руководство / напоминание** об аннотациях типов в Python. Оно охватывает только минимум, необходимый для их использования с **FastAPI**... что на самом деле очень мало.
**FastAPI** целиком основан на этих подсказках типов — они дают ему множество преимуществ и выгод.
**FastAPI** целиком основан на этих аннотациях типов — они дают ему множество преимуществ и выгод.
Но даже если вы никогда не используете **FastAPI**, вам будет полезно немного узнать о них.
/// note | Примечание
Если вы являетесь экспертом в Python и уже знаете всё о подсказках типов, переходите к следующей главе.
Если вы являетесь экспертом в Python и уже знаете всё об аннотациях типов, переходите к следующей главе.
///
@@ -76,7 +76,7 @@ John Doe
Вот и всё.
Это и есть «подсказки типов»:
Это и есть «аннотации типов»:
{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *}
@@ -90,9 +90,9 @@ John Doe
Здесь мы используем двоеточия (`:`), а не знак равенства (`=`).
И добавление подсказок типов обычно не меняет поведение программы по сравнению с вариантом без них.
И добавление аннотаций типов обычно не меняет поведение программы по сравнению с вариантом без них.
Но теперь представьте, что вы снова посередине написания этой функции, только уже с подсказками типов.
Но теперь представьте, что вы снова посередине написания этой функции, только уже с аннотациями типов.
В тот же момент вы пробуете вызвать автозавершение с помощью `Ctrl+Space` — и видите:
@@ -104,7 +104,7 @@ John Doe
## Больше мотивации { #more-motivation }
Посмотрите на эту функцию — у неё уже есть подсказки типов:
Посмотрите на эту функцию — у неё уже есть аннотации типов:
{* ../../docs_src/python_types/tutorial003_py310.py hl[1] *}
@@ -118,7 +118,7 @@ John Doe
## Объявление типов { #declaring-types }
Вы только что увидели основное место, где объявляют подсказки типов — параметры функции.
Вы только что увидели основное место, где объявляют аннотации типов — параметры функции.
Это также основное место, где вы будете использовать их с **FastAPI**.
@@ -293,9 +293,9 @@ def some_function(data: Any):
Вы увидите намного больше всего этого на практике в [Учебник - Руководство пользователя](tutorial/index.md).
## Подсказки типов с аннотациями метаданных { #type-hints-with-metadata-annotations }
## Аннотации типов с аннотациями метаданных { #type-hints-with-metadata-annotations }
В Python также есть возможность добавлять **дополнительные <dfn title="Данные о данных, в данном случае — информация о типе, например описание.">метаданные</dfn>** к подсказкам типов с помощью `Annotated`.
В Python также есть возможность добавлять **дополнительные <dfn title="Данные о данных, в данном случае — информация о типе, например описание.">метаданные</dfn>** к аннотациям типов с помощью `Annotated`.
Вы можете импортировать `Annotated` из `typing`.
@@ -321,16 +321,16 @@ def some_function(data: Any):
## Аннотации типов в **FastAPI** { #type-hints-in-fastapi }
**FastAPI** использует эти подсказки типов для выполнения нескольких задач.
**FastAPI** использует эти аннотации типов для выполнения нескольких задач.
С **FastAPI** вы объявляете параметры с подсказками типов и получаете:
С **FastAPI** вы объявляете параметры с аннотациями типов и получаете:
* **Поддержку редактора кода**.
* **Проверки типов**.
...и **FastAPI** использует эти же объявления для:
* **Определения требований**: из path-параметров пути запроса, query-параметров, HTTP-заголовков, тел запросов, зависимостей и т.д.
* **Определения требований**: из path-параметров HTTP-запроса, query-параметров, HTTP-заголовков, тел запросов, зависимостей и т.д.
* **Преобразования данных**: из HTTP-запроса к требуемому типу.
* **Валидации данных**: приходящих с каждого HTTP-запроса:
* Генерации **автоматических ошибок**, возвращаемых клиенту, когда данные некорректны.
+46 -34
View File
@@ -17,16 +17,16 @@
```
.
├── app
   ├── __init__.py
   ├── main.py
   ├── dependencies.py
   └── routers
   │ ├── __init__.py
   │ ├── items.py
   │ └── users.py
   └── internal
   ├── __init__.py
   └── admin.py
├── __init__.py
├── main.py
├── dependencies.py
└── routers
│ ├── __init__.py
│ ├── items.py
│ └── users.py
└── internal
├── __init__.py
└── admin.py
```
/// tip | Подсказка
@@ -58,16 +58,16 @@ from app.routers import items
```bash
.
├── app # "app" пакет
├── app # "app" — Python-пакет
│   ├── __init__.py # этот файл превращает "app" в "Python-пакет"
│   ├── main.py # модуль "main", напр.: import app.main
│   ├── dependencies.py # модуль "dependencies", напр.: import app.dependencies
│   └── routers # подпакет "routers"
│   │ ├── __init__.py # превращает "routers" в подпакет
│   └── routers # "routers" — "Python-подпакет"
│   │ ├── __init__.py # превращает "routers" в "Python-подпакет"
│   │ ├── items.py # подмодуль "items", напр.: import app.routers.items
│   │ └── users.py # подмодуль "users", напр.: import app.routers.users
│   └── internal # подпакет "internal"
│   ├── __init__.py # превращает "internal" в подпакет
│   └── internal # "internal" — "Python-подпакет"
│   ├── __init__.py # превращает "internal" в "Python-подпакет"
│   └── admin.py # подмодуль "admin", напр.: import app.internal.admin
```
@@ -121,7 +121,7 @@ from app.routers import items
/// tip | Подсказка
Для простоты мы воспользовались выдуманным заголовком.
Для простоты мы воспользовались выдуманным HTTP-заголовком.
В реальных случаях для получения наилучших результатов используйте интегрированные [утилиты безопасности](security/index.md).
@@ -163,9 +163,9 @@ async def read_item(item_id: str):
В нашем случае префиксом является `/items`.
Мы также можем добавить список `tags` и дополнительные `responses`, которые будут применяться ко всем *операциям пути*, включённым в этот маршрутизатор.
Мы также можем добавить список `tags` и дополнительные `responses`, которые будут применяться ко всем *операциям пути*, включённым в этот роутер.
И ещё мы можем добавить список `dependencies`, которые будут добавлены ко всем *операциям пути* в маршрутизаторе и будут выполняться/разрешаться для каждого HTTP-запроса к ним.
И ещё мы можем добавить список `dependencies`, которые будут добавлены ко всем *операциям пути* в роутере и будут выполняться/разрешаться для каждого HTTP-запроса к ним.
/// tip | Подсказка
@@ -185,7 +185,7 @@ async def read_item(item_id: str):
* Все они будут включать предопределённые `responses`.
* Все эти *операции пути* будут иметь список `dependencies`, вычисляемых/выполняемых перед ними.
* Если вы также объявите зависимости в конкретной *операции пути*, **они тоже будут выполнены**.
* Сначала выполняются зависимости маршрутизатора, затем [`dependencies` в декораторе](dependencies/dependencies-in-path-operation-decorators.md), и затем обычные параметрические зависимости.
* Сначала выполняются зависимости роутера, затем [`dependencies` в декораторе](dependencies/dependencies-in-path-operation-decorators.md), и затем обычные параметрические зависимости.
* Вы также можете добавить [`Security`-зависимости с `scopes`](../advanced/security/oauth2-scopes.md).
/// tip | Подсказка
@@ -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`)...
@@ -285,7 +285,7 @@ from ...dependencies import get_token_header
Эта последняя операция пути будет иметь комбинацию тегов: `["items", "custom"]`.
И в документации у неё будут оба ответа: один для `404` и один для `403`.
И в документации у неё будут оба HTTP-ответа: один для `404` и один для `403`.
///
@@ -325,7 +325,7 @@ from .routers import items, users
означает:
* Начать в том же пакете, в котором находится этот модуль (файл `app/main.py`) расположен в (каталоге `app/`)...
* Начать в том же пакете, в котором находится этот модуль (файл `app/main.py`) (каталог `app/`)...
* найти подпакет `routers` (каталог `app/routers/`)...
* и импортировать из него подмодули `items` (файл `app/routers/items.py`) и `users` (файл `app/routers/users.py`)...
@@ -392,21 +392,21 @@ from .routers.users import router
С помощью `app.include_router()` мы можем добавить каждый `APIRouter` в основное приложение `FastAPI`.
Он включит все маршруты этого маршрутизатора как часть приложения.
Он включит все маршруты этого роутера как часть приложения.
/// note | Технические детали
Фактически, внутри он создаст *операцию пути* для каждой *операции пути*, объявленной в `APIRouter`.
FastAPI сохраняет исходный `APIRouter` и его `APIRoute` активными, когда роутер включается в основное приложение.
Так что под капотом всё будет работать так, как будто всё было одним приложением.
Это означает, что пользовательские подклассы `APIRouter` и `APIRoute` по-прежнему участвуют после подключения роутера.
///
/// tip | Подсказка
При подключении маршрутизаторов не нужно беспокоиться о производительности.
При подключении роутеров не нужно беспокоиться о производительности.
Это займёт микросекунды и произойдёт только при старте.
Это сделано максимально лёгким и не добавляет накладных расходов на каждый запрос.
Так что это не повлияет на производительность. ⚡
@@ -435,7 +435,7 @@ from .routers.users import router
* Префикс `/admin`.
* Тег `admin`.
* Зависимость `get_token_header`.
* Ответ `418`. 🍵
* HTTP-ответ `418`. 🍵
Но это повлияет только на этот `APIRouter` в нашем приложении, а не на любой другой код, который его использует.
@@ -459,9 +459,9 @@ from .routers.users import router
`APIRouter` не «монтируются», они не изолированы от остального приложения.
Это потому, что мы хотим включить их *операции пути* в OpenAPI-схему и пользовательские интерфейсы.
Это потому, что мы хотим включить их *операции пути* в схему OpenAPI и пользовательские интерфейсы.
Так как мы не можем просто изолировать их и «смонтировать» независимо от остального, *операции пути* «клонируются» (пересоздаются), а не включаются напрямую.
FastAPI сохраняет исходные роутеры и операции пути активными и комбинирует префиксы роутеров, зависимости, теги, HTTP-ответы и другие метаданные при обработке HTTP-запросов и генерации OpenAPI.
///
@@ -516,15 +516,15 @@ $ fastapi dev
<img src="/img/tutorial/bigger-applications/image01.png">
## Подключение одного и того же маршрутизатора несколько раз с разными `prefix` { #include-the-same-router-multiple-times-with-different-prefix }
## Подключение одного и того же роутера несколько раз с разными `prefix` { #include-the-same-router-multiple-times-with-different-prefix }
Вы можете использовать `.include_router()` несколько раз с *одним и тем же* маршрутизатором, используя разные префиксы.
Вы можете использовать `.include_router()` несколько раз с *одним и тем же* роутером, используя разные префиксы.
Это может быть полезно, например, чтобы предоставить доступ к одному и тому же API с разными префиксами, например `/api/v1` и `/api/latest`.
Это продвинутое использование, которое вам может и не понадобиться, но оно есть на случай, если понадобится.
## Подключение `APIRouter` в другой `APIRouter` { #include-an-apirouter-in-another }
## Подключение `APIRouter` в другой `APIRouter` { #include-an-apirouter-in-another }
Точно так же, как вы можете подключить `APIRouter` к приложению `FastAPI`, вы можете подключить `APIRouter` к другому `APIRouter`, используя:
@@ -532,4 +532,16 @@ $ fastapi dev
router.include_router(other_router)
```
Убедитесь, что вы сделали это до подключения `router` к приложению `FastAPI`, чтобы *операции пути* из `other_router` также были подключены.
Вы можете сделать это до или после подключения `router` к приложению `FastAPI`. FastAPI всё равно включит *операции пути* из `other_router` в маршрутизацию и OpenAPI.
То же относится к *операциям пути*, добавленным позже в роутеры. Они также будут видны через более раннее включение.
/// warning | Технические детали
Избегайте прямой мутации `router.routes` после включения роутера. FastAPI рассматривает включение роутера как «живое», поэтому исходный роутер и его маршруты остаются частью маршрутизации и генерации OpenAPI.
Используйте документированные API, такие как декораторы операций пути и `.include_router()`, чтобы добавлять маршруты и роутеры.
Считайте `router.routes` низкоуровневым деревом маршрутов, которое может содержать определения маршрутов и включённые роутеры, и избегайте воспринимать его как плоский список итоговых операций пути.
///
@@ -108,7 +108,7 @@ q: str | None = None
{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *}
/// info | Информация
/// note | Заметка
`Body` также имеет все те же дополнительные параметры валидации и метаданных, как у `Query`, `Path` и других, которые вы увидите позже.
@@ -123,7 +123,7 @@ q: str | None = None
Но если вы хотите чтобы он ожидал JSON с ключом `item` с содержимым модели внутри, также как это происходит при объявлении дополнительных body-параметров, вы можете использовать специальный параметр `embed` у типа `Body`:
```Python
item: Item = Body(embed=True)
item: Annotated[Item, Body(embed=True)]
```
так же, как в этом примере:
+9 -8
View File
@@ -12,11 +12,12 @@
## Поля-списки с параметром типа { #list-fields-with-type-parameter }
В Python есть специальный способ объявлять списки с внутренними типами, или «параметрами типа»:
Но в Python есть специальный способ объявлять списки с внутренними типами, или «параметрами типа»:
### Объявите `list` с параметром типа { #declare-a-list-with-a-type-parameter }
Для объявления типов, у которых есть параметры типа (внутренние типы), таких как `list`, `dict`, `tuple`, передайте внутренний(ие) тип(ы) как «параметры типа», используя квадратные скобки: `[` и `]`
Для объявления типов, у которых есть параметры типа (внутренние типы), таких как `list`, `dict`, `tuple`,
передайте внутренний(ие) тип(ы) как «параметры типа», используя квадратные скобки: `[` и `]`
```Python
my_list: list[str]
@@ -109,7 +110,7 @@ my_list: list[str]
{* ../../docs_src/body_nested_models/tutorial006_py310.py hl[18] *}
Такая реализация будет ожидать (конвертировать, валидировать, документировать и т.д.) JSON-содержимое в следующем формате:
Такая реализация будет ожидать (конвертировать, валидировать, документировать и т.д.) JSON-тело запроса в следующем формате:
```JSON hl_lines="11"
{
@@ -135,7 +136,7 @@ my_list: list[str]
}
```
/// info | Информация
/// note | Примечание
Заметьте, что теперь у ключа `images` есть список объектов изображений.
@@ -147,15 +148,15 @@ my_list: list[str]
{* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *}
/// info | Информация
/// note | Примечание
Заметьте, что у объекта `Offer` есть список объектов `Item`, которые, в свою очередь, могут содержать необязательный список объектов `Image`
///
## Тела с чистыми списками элементов { #bodies-of-pure-lists }
## Тела запросов с чистыми списками элементов { #bodies-of-pure-lists }
Если верхний уровень значения тела JSON-объекта представляет собой JSON `array` (в Python — `list`), вы можете объявить тип в параметре функции, так же как в моделях Pydantic:
Если верхний уровень значения JSON-тела запроса представляет собой JSON `array` (в Python — `list`), вы можете объявить тип в параметре функции, так же как в моделях Pydantic:
```Python
images: list[Image]
@@ -211,7 +212,7 @@ images: list[Image]
С помощью **FastAPI** вы получаете максимальную гибкость, предоставляемую моделями Pydantic, сохраняя при этом простоту, краткость и элегантность вашего кода.
И дополнительно вы получаете:
Но со всеми преимуществами:
* Поддержку редактора кода (автозавершение доступно везде!)
* Преобразование данных (также известно как парсинг / сериализация)
+2 -2
View File
@@ -8,7 +8,7 @@
Чтобы объявить тело **запроса**, используйте модели [Pydantic](https://docs.pydantic.dev/), со всей их мощью и преимуществами.
/// info | Информация
/// note | Заметка
Чтобы отправить данные, используйте один из методов: `POST` (чаще всего), `PUT`, `DELETE` или `PATCH`.
@@ -70,7 +70,7 @@
* Считает тело запроса как JSON.
* Приведёт данные к соответствующим типам (если потребуется).
* Проведёт валидацию данных.
* Если данные некорректны, вернёт понятную и наглядную ошибку, указывающую, где именно и что было некорректно.
* Если данные некорректны, вернёт понятную и наглядную ошибку, указывающую, где именно and что было некорректно.
* Передаст полученные данные в параметр `item`.
* Поскольку внутри функции вы объявили его с типом `Item`, у вас будет поддержка со стороны редактора кода (автозавершение и т.п.) для всех атрибутов и их типов.
* Сгенерирует определения [JSON Schema](https://json-schema.org) для вашей модели; вы можете использовать их и в других местах, если это имеет смысл для вашего проекта.
+1 -1
View File
@@ -32,7 +32,7 @@
<img src="/img/tutorial/cookie-param-models/image01.png">
</div>
/// info | Дополнительная информация
/// note | Заметка
Имейте в виду, что, поскольку **браузеры обрабатывают cookies** особым образом и под капотом, они **не** позволят **JavaScript** легко получить доступ к ним.
+2 -2
View File
@@ -24,13 +24,13 @@
///
/// info | Дополнительная информация
/// note | Примечание
Для объявления cookies, вам нужно использовать `Cookie`, иначе параметры будут интерпретированы как параметры запроса.
///
/// info | Дополнительная информация
/// note | Примечание
Имейте в виду, что, поскольку **браузеры обрабатывают cookies** особым образом и «за кулисами», они **не** позволяют **JavaScript** просто так получать к ним доступ.
+5 -5
View File
@@ -1,10 +1,10 @@
# Отладка { #debugging }
Вы можете подключить отладчик в своем редакторе, например, в Visual Studio Code или PyCharm.
Вы можете подключить отладчик в своем редакторе кода, например, в Visual Studio Code или PyCharm.
## Вызов `uvicorn` { #call-uvicorn }
В вашем FastAPI приложении, импортируйте и вызовите `uvicorn` напрямую:
В вашем FastAPI приложении, импортируйте и запустите `uvicorn` напрямую:
{* ../../docs_src/debugging/tutorial001_py310.py hl[1,15] *}
@@ -62,7 +62,7 @@ from myapp import app
# Еще немного кода
```
то автоматическая создаваемая внутри файла `myapp.py` переменная `__name__` будет иметь значение отличающееся от `"__main__"`.
то автоматически создаваемая внутри файла `myapp.py` переменная `__name__` будет иметь значение, отличающееся от `"__main__"`.
Следовательно, строка:
@@ -72,7 +72,7 @@ from myapp import app
не будет выполнена.
/// info | Информация
/// note | Примечание
Для получения дополнительной информации, ознакомьтесь с [официальной документацией Python](https://docs.python.org/3/library/__main__.html).
@@ -80,7 +80,7 @@ from myapp import app
## Запуск вашего кода с помощью отладчика { #run-your-code-with-your-debugger }
Так как вы запускаете сервер Uvicorn непосредственно из вашего кода, вы можете вызвать Python программу (ваше FastAPI приложение) напрямую из отладчика.
Так как вы запускаете сервер Uvicorn непосредственно из вашего кода, вы можете запустить Python программу (ваше FastAPI приложение) напрямую из отладчика.
---
@@ -28,7 +28,7 @@
///
/// info | Примечание
/// note | Примечание
В этом примере мы используем выдуманные пользовательские HTTP-заголовки `X-Key` и `X-Token`.
@@ -123,7 +123,7 @@ FastAPI поддерживает зависимости, которые выпо
### Всегда делайте `raise` в зависимостях с `yield` и `except` { #always-raise-in-dependencies-with-yield-and-except }
Если вы ловите исключение в зависимости с `yield`, то, если вы не вызываете другой `HTTPException` или что-то подобное, вам следует повторно вызвать исходное исключение.
Если вы ловите исключение в зависимости с `yield`, то, если вы не вызываете другой `HTTPException` или что-то подобное, **вам следует повторно вызвать исходное исключение**.
Вы можете повторно вызвать то же самое исключение с помощью `raise`:
@@ -170,7 +170,7 @@ participant tasks as Background tasks
end
```
/// info | Дополнительная информация
/// note | Примечание
Клиенту будет отправлен только **один ответ**. Это может быть один из ответов об ошибке или ответ от *операции пути*.
@@ -219,7 +219,7 @@ participant operation as Функция-обработчик пути
Note over dep_req: Выполнить код до yield
dep_req ->> dep_func: Передать значение
Note over dep_func: Выполнить код до yield
dep_func ->> operation: Выполнить функцию-обработчик пути
dep_func ->> operation: Выполнить функцию-обработчика пути
operation ->> dep_func: Выход из функции-обработчика пути
Note over dep_func: Выполнить код после yield
Note over dep_func: ✅ Зависимость закрыта
@@ -234,6 +234,7 @@ participant operation as Функция-обработчик пути
Зависимости с `yield` со временем эволюционировали, чтобы покрыть разные сценарии и исправить некоторые проблемы.
Если вы хотите посмотреть, что менялось в разных версиях FastAPI, вы можете прочитать об этом подробнее в продвинутом руководстве: [Продвинутые зависимости — зависимости с `yield`, `HTTPException`, `except` и фоновыми задачами](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks).
## Контекстные менеджеры { #context-managers }
### Что такое «контекстные менеджеры» { #what-are-context-managers }
+2 -2
View File
@@ -51,7 +51,7 @@
А затем просто возвращает `dict`, содержащий эти значения.
/// info | Информация
/// note | Примечание
FastAPI добавил поддержку `Annotated` (и начал рекомендовать его использование) в версии 0.95.0.
@@ -106,7 +106,7 @@ common_parameters --> read_users
Таким образом, вы пишете общий код один раз, а **FastAPI** позаботится о его вызове для ваших *операций пути*.
/// check | Проверка
/// tip | Подсказка
Обратите внимание, что вам не нужно создавать специальный класс и передавать его куда-то в **FastAPI**, чтобы «зарегистрировать» его или что-то подобное.
@@ -6,9 +6,9 @@
**FastAPI** сам займётся их управлением.
## Первая зависимость { #first-dependency-dependable }
## Первая «зависимость» { #first-dependency-dependable }
Можно создать первую зависимость следующим образом:
Можно создать первую «зависимость» следующим образом:
{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[8:9] *}
@@ -35,7 +35,7 @@
{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *}
/// info | Дополнительная информация
/// note | Примечание
Обратите внимание, что мы объявляем только одну зависимость в *функции операции пути* - `query_or_cookie_extractor`.
+12 -12
View File
@@ -12,7 +12,7 @@
При этом у вас останутся те же возможности, что и до сих пор:
* Отличная поддержка редактора кода.
* Преобразование данных из входящих запросов.
* Преобразование данных из входящих HTTP-запросов.
* Преобразование данных для ответа.
* Валидация данных.
* Автоматическая аннотация и документация.
@@ -23,32 +23,32 @@
* `UUID`:
* Стандартный "Универсальный уникальный идентификатор", используемый в качестве идентификатора во многих базах данных и системах.
* В запросах и ответах будет представлен как `str`.
* В HTTP-запросах и HTTP-ответах будет представлен как `str`.
* `datetime.datetime`:
* Встроенный в Python `datetime.datetime`.
* В запросах и ответах будет представлен как `str` в формате ISO 8601, например: `2008-09-15T15:53:00+05:00`.
* В HTTP-запросах и HTTP-ответах будет представлен как `str` в формате ISO 8601, например: `2008-09-15T15:53:00+05:00`.
* `datetime.date`:
* Встроенный в Python `datetime.date`.
* В запросах и ответах будет представлен как `str` в формате ISO 8601, например: `2008-09-15`.
* В HTTP-запросах и HTTP-ответах будет представлен как `str` в формате ISO 8601, например: `2008-09-15`.
* `datetime.time`:
* Встроенный в Python `datetime.time`.
* В запросах и ответах будет представлен как `str` в формате ISO 8601, например: `14:23:55.003`.
* В HTTP-запросах и HTTP-ответах будет представлен как `str` в формате ISO 8601, например: `14:23:55.003`.
* `datetime.timedelta`:
* Встроенный в Python `datetime.timedelta`.
* В запросах и ответах будет представлен в виде общего количества секунд типа `float`.
* В HTTP-запросах и HTTP-ответах будет представлен в виде общего количества секунд типа `float`.
* Pydantic также позволяет представить его как "Кодировку разницы во времени ISO 8601", [см. документацию для получения дополнительной информации](https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers).
* `frozenset`:
* В запросах и ответах обрабатывается так же, как и `set`:
* В запросах будет прочитан список, исключены дубликаты и преобразован в `set`.
* В ответах `set` будет преобразован в `list`.
* В HTTP-запросах и HTTP-ответах обрабатывается так же, как и `set`:
* В HTTP-запросах будет прочитан список, исключены дубликаты и преобразован в `set`.
* В HTTP-ответах `set` будет преобразован в `list`.
* В сгенерированной схеме будет указано, что значения `set` уникальны (с помощью JSON-схемы `uniqueItems`).
* `bytes`:
* Встроенный в Python `bytes`.
* В запросах и ответах будет рассматриваться как `str`.
* В сгенерированной схеме будет указано, что это `str` в формате `binary`.
* В HTTP-запросах и HTTP-ответах будет рассматриваться как `str`.
* В сгенерированной схеме будет указано, что это `str` в "формате" `binary`.
* `Decimal`:
* Встроенный в Python `Decimal`.
* В запросах и ответах обрабатывается так же, как и `float`.
* В HTTP-запросах и HTTP-ответах обрабатывается так же, как и `float`.
* Вы можете проверить все допустимые типы данных Pydantic здесь: [Типы данных Pydantic](https://docs.pydantic.dev/latest/usage/types/types/).
## Пример { #example }
+1 -1
View File
@@ -208,4 +208,4 @@ some_variable: PlaneItem | CarItem
Используйте несколько Pydantic-моделей и свободно применяйте наследование для каждого случая.
Вам не обязательно иметь единственную модель данных для каждой сущности, если эта сущность должна иметь возможность быть в разных "состояниях". Как в случае с "сущностью" пользователя, у которого есть состояние, включающее `password`, `password_hash` и отсутствие пароля.
Вам не обязательно иметь единственную модель данных для каждой сущности, если эта сущность должна иметь возможность быть в разных "состояниях". **Пользователь** — пример такой "сущности", с состояниями, которые включают `password`, `password_hash` или отсутствие пароля.
+25 -33
View File
@@ -180,7 +180,7 @@ entrypoint = "backend.main:app"
from backend.main import app
```
### `fastapi dev` с путём { #fastapi-dev-with-path }
### `fastapi dev` с путём или с опцией CLI `--entrypoint` { #fastapi-dev-with-path-or-with-entrypoint-cli-option }
Вы также можете передать путь к файлу в команду `fastapi dev`, и она попытается определить объект приложения FastAPI для использования:
@@ -188,29 +188,19 @@ from backend.main import app
$ fastapi dev main.py
```
Но в этом случае вам придётся каждый раз помнить о передаче корректного пути при вызове команды `fastapi`.
Или вы можете передать опцию `--entrypoint` команде `fastapi dev`:
```console
$ fastapi dev --entrypoint main:app
```
Но в этом случае вам придётся каждый раз помнить о передаче корректного пути/entrypoint при вызове команды `fastapi`.
Кроме того, другие инструменты могут его не найти, например [Расширение VS Code](../editor-support.md) или [FastAPI Cloud](https://fastapicloud.com), поэтому рекомендуется использовать `entrypoint` в `pyproject.toml`.
### Разверните приложение (необязательно) { #deploy-your-app-optional }
При желании вы можете развернуть своё приложение FastAPI в [FastAPI Cloud](https://fastapicloud.com), перейдите и присоединитесь к списку ожидания, если ещё не сделали этого. 🚀
Если у вас уже есть аккаунт **FastAPI Cloud** (мы пригласили вас из списка ожидания 😉), вы можете развернуть приложение одной командой.
Перед развертыванием убедитесь, что вы вошли в систему:
<div class="termy">
```console
$ fastapi login
You are logged in to FastAPI Cloud 🚀
```
</div>
Затем разверните приложение:
При желании вы можете развернуть своё приложение FastAPI в [FastAPI Cloud](https://fastapicloud.com) одной командой. 🚀
<div class="termy">
@@ -226,6 +216,8 @@ Deploying to FastAPI Cloud...
</div>
CLI автоматически определит ваше приложение FastAPI и развернёт его в облаке. Если вы не вошли в систему, откроется браузер для завершения процесса аутентификации.
Готово! Теперь вы можете открыть своё приложение по этому URL. ✨
## Рассмотрим поэтапно { #recap-step-by-step }
@@ -252,9 +244,9 @@ Deploying to FastAPI Cloud...
Это будет основная точка взаимодействия для создания всего вашего API.
### Шаг 3: создайте *операцию пути (path operation)* { #step-3-create-a-path-operation }
### Шаг 3: создайте *операцию пути* { #step-3-create-a-path-operation }
#### Путь (path) { #path }
#### Путь { #path }
Здесь «путь» — это последняя часть URL, начиная с первого символа `/`.
@@ -270,7 +262,7 @@ https://example.com/items/foo
/items/foo
```
/// info | Информация
/// note | Примечание
«Путь» также часто называют «эндпоинт» или «маршрут».
@@ -278,7 +270,7 @@ https://example.com/items/foo
При создании API «путь» — это основной способ разделения «задач» и «ресурсов».
#### Операция (operation) { #operation }
#### Операция { #operation }
«Операция» здесь — это один из HTTP-«методов».
@@ -311,18 +303,18 @@ https://example.com/items/foo
Таким образом, в OpenAPI каждый HTTP-метод называется «операцией».
Мы тоже будем называть их «операциями».
Мы тоже будем называть их «**операциями**».
#### Определите *декоратор операции пути (path operation decorator)* { #define-a-path-operation-decorator }
#### Определите *декоратор операции пути* { #define-a-path-operation-decorator }
{* ../../docs_src/first_steps/tutorial001_py310.py hl[6] *}
`@app.get("/")` сообщает **FastAPI**, что функция прямо под ним отвечает за обработку запросов, поступающих:
`@app.get("/")` сообщает **FastAPI**, что функция прямо под ним отвечает за обработку HTTP-запросов, поступающих:
* по пути `/`
* с использованием <dfn title="метод HTTP GET"><code>get</code> операции</dfn>
* с использованием <dfn title="HTTP-метод GET">операции <code>get</code></dfn>
/// info | Информация о `@decorator`
/// note | Информация о `@decorator`
Синтаксис `@something` в Python называется «декоратор».
@@ -361,9 +353,9 @@ https://example.com/items/foo
///
### Шаг 4: определите **функцию операции пути** { #step-4-define-the-path-operation-function }
### Шаг 4: определите **функцию-обработчик пути** { #step-4-define-the-path-operation-function }
Вот наша «функция операции пути»:
Вот наша «**функция-обработчик пути**»:
* **путь**: `/`.
* **операция**: `get`.
@@ -373,7 +365,7 @@ https://example.com/items/foo
Это функция на Python.
**FastAPI** будет вызывать её каждый раз, когда получает запрос к URL «`/`» с операцией `GET`.
**FastAPI** будет вызывать её каждый раз, когда получает HTTP-запрос к URL «`/`» с операцией `GET`.
В данном случае это асинхронная (`async`) функция.
@@ -411,7 +403,7 @@ https://example.com/items/foo
Он переносит тот же **опыт разработчика** при создании приложений с FastAPI на их **развертывание** в облаке. 🎉
FastAPI Cloud — основной спонсор и источник финансирования для open-source проектов «FastAPI и друзья». ✨
FastAPI Cloud — основной спонсор и источник финансирования для open-source проектов *FastAPI и друзья*. ✨
#### Развертывание у других облачных провайдеров { #deploy-to-other-cloud-providers }
@@ -424,6 +416,6 @@ FastAPI — open-source и основан на стандартах. Вы мож
* Импортируйте `FastAPI`.
* Создайте экземпляр `app`.
* Напишите **декоратор операции пути**, например `@app.get("/")`.
* Определите **функцию операции пути**; например, `def root(): ...`.
* Определите **функцию-обработчик пути**; например, `def root(): ...`.
* Запустите сервер разработки командой `fastapi dev`.
* При желании разверните приложение командой `fastapi deploy`.
+133
View File
@@ -0,0 +1,133 @@
# Фронтенд { #frontend }
Вы можете «отдавать» статические фронтенд-приложения с помощью `app.frontend()` (или `router.frontend()`).
Это полезно для фронтенд-инструментов, которые генерируют статические файлы, таких как React с Vite, TanStack Router, Astro, Vue, Svelte, Angular, Solid и других.
С такими инструментами обычно есть этап сборки фронтенда с помощью команды вроде:
```bash
npm run build
```
Она сгенерирует директорию вроде `./dist/` с файлами вашего фронтенда.
Вы можете использовать `app.frontend()`, чтобы «отдавать» эту директорию, следуя соглашениям, которые требуются этим фронтенд-фреймворкам.
**FastAPI** сначала проверяет *операции пути*. Файлы фронтенда проверяются только если не совпал ни один обычный маршрут, поэтому ваш API не будет затронут.
## Отдача фронтенда { #serve-a-frontend }
После сборки фронтенда, например с помощью `npm run build`, поместите сгенерированные файлы в директорию, например `dist`.
Структура вашего проекта может выглядеть так:
```text
.
├── pyproject.toml
├── app
│ ├── __init__.py
│ └── main.py
└── dist
├── index.html
└── assets
└── app.js
```
Затем «отдавайте» её с помощью `app.frontend()`:
{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *}
При этом запрос к `/assets/app.js` может отдать `dist/assets/app.js`.
Если у вас также есть *операция пути* **FastAPI**, приоритет будет у *операции пути*.
## Маршрутизация на стороне клиента { #client-side-routing }
Многие фронтенд-приложения, включая **single-page apps** (SPA), используют маршрутизацию на стороне клиента. Путь вроде `/dashboard/settings` может не быть реальным файлом, но фреймворк возьмёт на себя его обработку.
Поэтому, если обратиться к этому URL напрямую (а не перейти к нему через приложение), backend должен отдать фронтенд-приложение из `index.html`, чтобы затем фронтенд-фреймворк мог обработать маршрутизацию на стороне клиента.
Для этого используйте `fallback="index.html"`:
{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *}
**FastAPI** использует этот fallback только для запросов `GET` и `HEAD`, которые похожи на навигацию в браузере. Отсутствующие файлы, такие как JavaScript, CSS и изображения, по-прежнему возвращают `404`.
Запросы с другими методами, например `POST` или `PUT`, к путям, которые совпадают только с fallback фронтенда, также возвращают `404`. Обычные *операции пути* **FastAPI** по-прежнему имеют более высокий приоритет, чем маршруты фронтенда.
/// tip | Совет
По умолчанию `fallback` имеет значение `fallback="auto"`. В большинстве случаев вам не нужно будет указывать `fallback`. Подробности ниже.
///
Именно такое поведение нужно для многих фронтенд-приложений, которые используют маршрутизацию на стороне клиента, например React с TanStack Router, Vue, Angular, SvelteKit или Solid.
## Кастомная страница 404 { #custom-404-page }
Вы также можете отдавать статическую страницу `404.html` для отсутствующих путей фронтенда:
{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *}
Этот HTTP-ответ сохраняет статус-код `404`.
В этом случае **FastAPI** не будет отдавать `index.html` для отсутствующих путей фронтенда. Вместо этого он вернёт файл `404.html`.
/// tip | Совет
По умолчанию `fallback` имеет значение `fallback="auto"`. При этом, если найден файл `404.html`, он будет автоматически использован как fallback.
Поэтому обычно можно не указывать аргумент `fallback`.
///
Это полезно с фронтенд-инструментами, которые генерируют статические HTML-файлы для каждой страницы, например Astro.
## Автоматический fallback { #fallback-auto }
По умолчанию `app.frontend()` использует `fallback="auto"`.
Если в директории фронтенда есть файл `404.html`, отсутствующие пути фронтенда отдают этот файл со статус-кодом `404`.
В противном случае, если есть файл `index.html`, отсутствующие пути навигации в браузере отдают `index.html`, что и ожидают многие фронтенд-приложения с маршрутизацией на стороне клиента.
Поэтому в большинстве случаев можно использовать `app.frontend("/", directory="dist")` без указания аргумента `fallback`.
{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *}
## Отключение fallback { #disable-fallback }
Если вы не хотите отдавать fallback-файл для отсутствующих путей фронтенда, используйте `fallback=None`:
{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *}
Тогда отсутствующие пути фронтенда будут возвращать обычный `404`.
## Проверка директории { #check-directory }
По умолчанию `app.frontend()` проверяет, что директория существует, при создании приложения.
Это помогает рано обнаруживать ошибки конфигурации. Например, если отсутствует директория с результатом сборки фронтенда, **FastAPI** вызовет ошибку при запуске.
Если ваши фронтенд-файлы создаются позже, например отдельным этапом сборки после создания объекта приложения, установите `check_dir=False`:
{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *}
С `check_dir=False` **FastAPI** не будет проверять директорию при создании приложения. Если настроенная директория всё ещё отсутствует во время обработки HTTP-запроса, **FastAPI** вызовет ошибку тогда.
## Использование с `APIRouter` { #use-it-with-apirouter }
Вы также можете добавить фронтенд-файлы в `APIRouter` и включить его с префиксом:
{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *}
В этом примере пути фронтенда отдаются под `/app`.
Любые обычные *операции пути* в приложении всё равно будут иметь приоритет, включая операции в других роутерах.
## Только статический результат сборки { #static-build-output-only }
`app.frontend()` отдаёт файлы, уже сгенерированные сборкой вашего фронтенда.
Он не запускает server-side rendering. Он предназначен для фронтенд-фреймворков, которые генерируют статические файлы, а не для фреймворков, которым требуется динамический рендеринг на сервере для каждого HTTP-запроса.
+30 -30
View File
@@ -13,11 +13,11 @@
В таких случаях обычно возвращают **HTTP статус-код** в диапазоне **400** (от 400 до 499).
Они похожи на двухсотые HTTP статус-коды (от 200 до 299), которые означают, что запрос обработан успешно.
Они похожи на двухсотые HTTP статус-коды (от 200 до 299). Эти статус-коды "200" означают, что в HTTP-запросе в каком-то смысле был "успех".
Четырёхсотые статус-коды означают, что ошибка произошла по вине клиента.
HTTP статус-коды в диапазоне 400 означают, что произошла ошибка со стороны клиента.
Помните ли ошибки **"404 Not Found "** (и шутки) ?
Помните все эти ошибки **"404 Not Found"** (и шутки)?
## Использование `HTTPException` { #use-httpexception }
@@ -31,19 +31,19 @@
`HTTPException` - это обычное исключение Python с дополнительными данными, актуальными для API.
Поскольку это исключение Python, то его не `возвращают`, а `вызывают`.
Поскольку это исключение Python, то его не `return`, а `raise`.
Это также означает, что если вы находитесь внутри функции, которая вызывается внутри вашей *функции операции пути*, и вы поднимаете `HTTPException` внутри этой функции, то она не будет выполнять остальной код в *функции операции пути*, а сразу завершит запрос и отправит HTTP-ошибку из `HTTPException` клиенту.
Это также означает, что если вы находитесь внутри вспомогательной функции, которая вызывается внутри вашей *функции-обработчика пути*, и вы вызываете `HTTPException` изнутри этой вспомогательной функции, то остальной код в *функции-обработчике пути* выполняться не будет, запрос сразу завершится, а HTTP-ошибка из `HTTPException` будет отправлена клиенту.
О том, насколько выгоднее `вызывать` исключение, чем `возвращать` значение, будет рассказано в разделе, посвященном зависимостям и безопасности.
Преимущество вызова исключения перед возвратом значения станет более очевидным в разделе о зависимостях и безопасности.
В данном примере, когда клиент запрашивает элемент по несуществующему ID, возникает исключение со статус-кодом `404`:
В данном примере, когда клиент запрашивает элемент по несуществующему ID, вызовите исключение со статус-кодом `404`:
{* ../../docs_src/handling_errors/tutorial001_py310.py hl[11] *}
### Возвращаемый ответ { #the-resulting-response }
Если клиент запросит `http://example.com/items/foo` (`item_id` `"foo"`), то он получит статус-код 200 и ответ в формате JSON:
Если клиент запросит `http://example.com/items/foo` (`item_id` `"foo"`), то он получит HTTP статус-код 200 и ответ в формате JSON:
```JSON
{
@@ -51,7 +51,7 @@
}
```
Но если клиент запросит `http://example.com/items/bar` (несуществующий `item_id` `"bar"`), то он получит статус-код 404 (ошибка "не найдено") и JSON-ответ в виде:
Но если клиент запросит `http://example.com/items/bar` (несуществующий `item_id` `"bar"`), то он получит HTTP статус-код 404 (ошибка "не найдено") и JSON-ответ в виде:
```JSON
{
@@ -69,13 +69,13 @@
///
## Добавление пользовательских заголовков { #add-custom-headers }
## Добавление пользовательских HTTP-заголовков { #add-custom-headers }
В некоторых ситуациях полезно иметь возможность добавлять пользовательские HTTP-заголовки к ошибке HTTP. Например, для некоторых типов безопасности.
В некоторых ситуациях полезно иметь возможность добавлять пользовательские HTTP-заголовки к HTTP-ошибке. Например, для некоторых типов безопасности.
Скорее всего, вам не потребуется использовать его непосредственно в коде.
Скорее всего, вам не потребуется использовать это непосредственно в коде.
Но в случае, если это необходимо для продвинутого сценария, можно добавить пользовательские заголовки:
Но в случае, если это необходимо для продвинутого сценария, можно добавить пользовательские HTTP-заголовки:
{* ../../docs_src/handling_errors/tutorial002_py310.py hl[14] *}
@@ -83,7 +83,7 @@
Вы можете добавить пользовательские обработчики исключений с помощью [тех же утилит обработки исключений из Starlette](https://www.starlette.dev/exceptions/).
Допустим, у вас есть пользовательское исключение `UnicornException`, которое вы (или используемая вами библиотека) можете `вызвать`.
Допустим, у вас есть пользовательское исключение `UnicornException`, которое вы (или используемая вами библиотека) можете вызвать с помощью `raise`.
И вы хотите обрабатывать это исключение глобально с помощью FastAPI.
@@ -95,7 +95,7 @@
Но оно будет обработано `unicorn_exception_handler`.
Таким образом, вы получите чистую ошибку с кодом состояния HTTP `418` и содержимым JSON:
Таким образом, вы получите чистую ошибку с HTTP статус-кодом `418` и содержимым JSON:
```JSON
{"message": "Oops! yolo did something. There goes a rainbow..."}
@@ -113,17 +113,17 @@
**FastAPI** имеет некоторые обработчики исключений по умолчанию.
Эти обработчики отвечают за возврат стандартных JSON-ответов при `вызове` `HTTPException` и при наличии в запросе недопустимых данных.
Эти обработчики отвечают за возврат стандартных JSON-ответов при вызове `HTTPException` с помощью `raise` и при наличии в HTTP-запросе недопустимых данных.
Вы можете переопределить эти обработчики исключений на свои собственные.
### Переопределение обработчика исключений проверки запроса { #override-request-validation-exceptions }
### Переопределение исключений валидации запроса { #override-request-validation-exceptions }
Когда запрос содержит недопустимые данные, **FastAPI** внутренне вызывает ошибку `RequestValidationError`.
Когда HTTP-запрос содержит недопустимые данные, **FastAPI** внутренне вызывает `RequestValidationError`.
А также включает в себя обработчик исключений по умолчанию.
А также включает в себя обработчик исключений по умолчанию для него.
Чтобы переопределить его, импортируйте `RequestValidationError` и используйте его с `@app.exception_handler(RequestValidationError)` для создания обработчика исключений.
Чтобы переопределить его, импортируйте `RequestValidationError` и используйте его с `@app.exception_handler(RequestValidationError)`, чтобы декорировать обработчик исключений.
Обработчик исключения получит объект `Request` и исключение.
@@ -146,7 +146,7 @@
}
```
вы получите текстовую версию:
вы получите текстовую версию с:
```
Validation errors:
@@ -171,7 +171,7 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa
/// warning | Внимание
Имейте в виду, что `RequestValidationError` содержит информацию об имени файла и строке, где произошла ошибка валидации, чтобы вы могли при желании отобразить её в логах с релевантными данными.
Имейте в виду, что `RequestValidationError` содержит информацию об имени файла и строке, где происходит ошибка валидации, чтобы вы могли при желании отобразить её в логах вместе с релевантной информацией.
Но это означает, что если вы просто преобразуете её в строку и вернёте эту информацию напрямую, вы можете допустить небольшую утечку информации о своей системе, поэтому здесь код извлекает и показывает каждую ошибку отдельно.
@@ -179,13 +179,13 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa
### Используйте тело `RequestValidationError` { #use-the-requestvalidationerror-body }
Ошибка `RequestValidationError` содержит полученное `тело` с недопустимыми данными.
Ошибка `RequestValidationError` содержит `body` (тело запроса), которое она получила с недопустимыми данными.
Вы можете использовать его при разработке приложения для регистрации тела и его отладки, возврата пользователю и т.д.
Вы можете использовать его при разработке приложения для логирования тела запроса и его отладки, возврата пользователю и т.д.
{* ../../docs_src/handling_errors/tutorial005_py310.py hl[14] *}
Теперь попробуйте отправить недействительный элемент, например:
Теперь попробуйте отправить недопустимый элемент, например:
```JSON
{
@@ -194,7 +194,7 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa
}
```
Вы получите ответ о том, что данные недействительны, содержащий следующее тело:
Вы получите ответ о том, что данные недопустимы, содержащий полученное тело запроса:
```JSON hl_lines="12-15"
{
@@ -215,7 +215,7 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa
}
```
#### `HTTPException` в FastAPI или в Starlette { #fastapis-httpexception-vs-starlettes-httpexception }
#### `HTTPException` в FastAPI и `HTTPException` в Starlette { #fastapis-httpexception-vs-starlettes-httpexception }
**FastAPI** имеет собственный `HTTPException`.
@@ -227,9 +227,9 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa
Но когда вы регистрируете обработчик исключений, вы должны зарегистрировать его для `HTTPException` от Starlette.
Таким образом, если какая-либо часть внутреннего кодa Starlette, расширение или плагин Starlette вызовет исключение Starlette `HTTPException`, ваш обработчик сможет перехватить и обработать его.
Таким образом, если какая-либо часть внутреннего кода Starlette, расширение или плагин Starlette вызовет исключение Starlette `HTTPException`, ваш обработчик сможет перехватить и обработать его.
В данном примере, чтобы иметь возможность использовать оба `HTTPException` в одном коде, исключения Starlette переименованы в `StarletteHTTPException`:
В данном примере, чтобы иметь возможность использовать оба `HTTPException` в одном коде, исключение Starlette переименовано в `StarletteHTTPException`:
```Python
from starlette.exceptions import HTTPException as StarletteHTTPException
@@ -241,4 +241,4 @@ from starlette.exceptions import HTTPException as StarletteHTTPException
{* ../../docs_src/handling_errors/tutorial006_py310.py hl[2:5,15,21] *}
В этом примере вы просто `выводите в терминал` ошибку с очень выразительным сообщением, но идея вам понятна. Вы можете использовать исключение, а затем просто повторно использовать стандартные обработчики исключений.
В этом примере вы просто выводите ошибку с очень выразительным сообщением, но идея вам понятна. Вы можете использовать исключение, а затем просто повторно использовать стандартные обработчики исключений.
+1
View File
@@ -1,5 +1,6 @@
# Учебник - Руководство пользователя { #tutorial-user-guide }
В этом руководстве шаг за шагом показано, как использовать **FastAPI** с большинством его функций.
Каждый раздел постепенно основывается на предыдущих, но структура разделяет темы, так что вы можете сразу перейти к нужной теме для решения ваших конкретных задач по API.
+13 -13
View File
@@ -11,10 +11,10 @@
| `title` | `str` | Заголовок API. |
| `summary` | `str` | Краткое резюме API. <small>Доступно начиная с OpenAPI 3.1.0, FastAPI 0.99.0.</small> |
| `description` | `str` | Краткое описание API. Может быть использован Markdown. |
| `version` | `string` | Версия API. Версия вашего собственного приложения, а не OpenAPI. К примеру `2.5.0`. |
| `terms_of_service` | `str` | Ссылка к условиям пользования API. Если указано, то это должен быть URL-адрес. |
| `contact` | `dict` | Контактная информация для открытого API. Может содержать несколько полей. <details><summary>поля <code>contact</code></summary><table><thead><tr><th>Параметр</th><th>Тип</th><th>Описание</th></tr></thead><tbody><tr><td><code>name</code></td><td><code>str</code></td><td>Идентификационное имя контактного лица/организации.</td></tr><tr><td><code>url</code></td><td><code>str</code></td><td>URL указывающий на контактную информацию. ДОЛЖЕН быть в формате URL.</td></tr><tr><td><code>email</code></td><td><code>str</code></td><td>Email адрес контактного лица/организации. ДОЛЖЕН быть в формате email адреса.</td></tr></tbody></table></details> |
| `license_info` | `dict` | Информация о лицензии открытого API. Может содержать несколько полей. <details><summary>поля <code>license_info</code></summary><table><thead><tr><th>Параметр</th><th>Тип</th><th>Описание</th></tr></thead><tbody><tr><td><code>name</code></td><td><code>str</code></td><td><strong>ОБЯЗАТЕЛЬНО</strong> (если установлен параметр <code>license_info</code>). Название лицензии, используемой для API.</td></tr><tr><td><code>identifier</code></td><td><code>str</code></td><td>Выражение лицензии [SPDX](https://spdx.org/licenses/) для API. Поле <code>identifier</code> взаимоисключающее с полем <code>url</code>. <small>Доступно начиная с OpenAPI 3.1.0, FastAPI 0.99.0.</small></td></tr><tr><td><code>url</code></td><td><code>str</code></td><td>URL, указывающий на лицензию, используемую для API. ДОЛЖЕН быть в формате URL.</td></tr></tbody></table></details> |
| `version` | `str` | Версия API. Версия вашего собственного приложения, а не OpenAPI. К примеру `2.5.0`. |
| `terms_of_service` | `str` | Ссылка на условия пользования API. Если указано, то это должен быть URL-адрес. |
| `contact` | `dict` | Контактная информация для открытого API. Может содержать несколько полей. <details><summary>поля <code>contact</code></summary><table><thead><tr><th>Параметр</th><th>Тип</th><th>Описание</th></tr></thead><tbody><tr><td><code>name</code></td><td><code>str</code></td><td>Идентификационное имя контактного лица/организации.</td></tr><tr><td><code>url</code></td><td><code>str</code></td><td>URL, указывающий на контактную информацию. ДОЛЖЕН быть в формате URL.</td></tr><tr><td><code>email</code></td><td><code>str</code></td><td>Email-адрес контактного лица/организации. ДОЛЖЕН быть в формате email-адреса.</td></tr></tbody></table></details> |
| `license_info` | `dict` | Информация о лицензии открытого API. Может содержать несколько полей. <details><summary>поля <code>license_info</code></summary><table><thead><tr><th>Параметр</th><th>Тип</th><th>Описание</th></tr></thead><tbody><tr><td><code>name</code></td><td><code>str</code></td><td><strong>ОБЯЗАТЕЛЬНО</strong> (если установлен параметр <code>license_info</code>). Название лицензии, используемой для API.</td></tr><tr><td><code>identifier</code></td><td><code>str</code></td><td>Выражение лицензии [SPDX](https://spdx.org/licenses/) для API. Поле <code>identifier</code> является взаимоисключающим с полем <code>url</code>. <small>Доступно начиная с OpenAPI 3.1.0, FastAPI 0.99.0.</small></td></tr><tr><td><code>url</code></td><td><code>str</code></td><td>URL, указывающий на лицензию, используемую для API. ДОЛЖЕН быть в формате URL.</td></tr></tbody></table></details> |
Вы можете задать их следующим образом:
@@ -48,7 +48,7 @@
* `name` (**обязательно**): `str`-значение с тем же именем тега, которое вы используете в параметре `tags` в ваших *операциях пути* и `APIRouter`ах.
* `description`: `str`-значение с кратким описанием для тега. Может содержать Markdown и будет отображаться в UI документации.
* `externalDocs`: `dict`-значение описывающее внешнюю документацию. Включает в себя:
* `externalDocs`: `dict`-значение, описывающее внешнюю документацию. Включает в себя:
* `description`: `str`-значение с кратким описанием для внешней документации.
* `url` (**обязательно**): `str`-значение с URL-адресом для внешней документации.
@@ -64,7 +64,7 @@
/// tip | Подсказка
Вам необязательно добавлять метаданные для всех используемых тегов
Вам необязательно добавлять метаданные для всех используемых тегов.
///
@@ -74,7 +74,7 @@
{* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *}
/// info | Дополнительная информация
/// note | Примечание
Узнайте больше о тегах в [Конфигурации операции пути](path-operation-configuration.md#tags).
@@ -94,11 +94,11 @@
## URL-адрес OpenAPI { #openapi-url }
По умолчанию схема OpenAPI отображена по адресу `/openapi.json`.
По умолчанию схема OpenAPI отдаётся по адресу `/openapi.json`.
Но вы можете изменить это с помощью параметра `openapi_url`.
К примеру, чтобы задать её отображение по адресу `/api/v1/openapi.json`:
К примеру, чтобы задать её отдачу по адресу `/api/v1/openapi.json`:
{* ../../docs_src/metadata/tutorial002_py310.py hl[3] *}
@@ -106,15 +106,15 @@
## URL-адреса документации { #docs-urls }
Вы можете изменить конфигурацию двух пользовательских интерфейсов документации, которые включены:
Вы можете изменить конфигурацию двух включённых пользовательских интерфейсов документации:
* **Swagger UI**: отображаемый по адресу `/docs`.
* **Swagger UI**: отдаётся по адресу `/docs`.
* Вы можете задать его URL с помощью параметра `docs_url`.
* Вы можете отключить это с помощью настройки `docs_url=None`.
* **ReDoc**: отображаемый по адресу `/redoc`.
* **ReDoc**: отдаётся по адресу `/redoc`.
* Вы можете задать его URL с помощью параметра `redoc_url`.
* Вы можете отключить это с помощью настройки `redoc_url=None`.
К примеру, чтобы задать отображение Swagger UI по адресу `/documentation` и отключить ReDoc:
К примеру, чтобы настроить отдачу Swagger UI по адресу `/documentation` и отключить ReDoc:
{* ../../docs_src/metadata/tutorial003_py310.py hl[3] *}
@@ -1,10 +1,10 @@
# Конфигурация операций пути { #path-operation-configuration }
# Конфигурация операции пути { #path-operation-configuration }
Существует несколько параметров, которые вы можете передать вашему *декоратору операций пути* для его настройки.
Существует несколько параметров, которые вы можете передать вашему *декоратору операции пути* для его настройки.
/// warning | Внимание
Помните, что эти параметры передаются непосредственно *декоратору операций пути*, а не вашей *функции-обработчику пути*.
Помните, что эти параметры передаются непосредственно *декоратору операции пути*, а не вашей *функции-обработчику пути*.
///
@@ -30,11 +30,11 @@
## Теги { #tags }
Вы можете добавлять теги к вашим *операциям пути*, добавив параметр `tags` с `list` заполненным `str`-значениями (обычно в нём только одна строка):
Вы можете добавлять теги к вашей *операции пути*, передав параметр `tags` с `list` из `str` (обычно в нём только одна строка):
{* ../../docs_src/path_operation_configuration/tutorial002_py310.py hl[15,20,25] *}
Они будут добавлены в схему OpenAPI и будут использованы в автоматической документации интерфейса:
Они будут добавлены в схему OpenAPI и будут использованы автоматическими интерфейсами документации:
<img src="/img/tutorial/path-operation-configuration/image01.png">
@@ -56,7 +56,7 @@
## Описание из строк документации { #description-from-docstring }
Так как описания обычно длинные и содержат много строк, вы можете объявить описание *операции пути* в <dfn title="многострочная строка, первое выражение внутри функции (не присвоенное какой-либо переменной), используемая для документации">строке документации</dfn> функции, и **FastAPI** прочитает её оттуда.
Так как описания обычно длинные и содержат много строк, вы можете объявить описание *операции пути* в <dfn title="многострочная строка, первое выражение внутри функции (не присвоенное какой-либо переменной), используемое для документации">строке документации</dfn> функции, и **FastAPI** прочитает её оттуда.
Вы можете использовать [Markdown](https://en.wikipedia.org/wiki/Markdown) в строке документации, и он будет интерпретирован и отображён корректно (с учетом отступа в строке документации).
@@ -72,13 +72,13 @@
{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *}
/// info | Дополнительная информация
/// note | Примечание
Помните, что `response_description` относится конкретно к ответу, а `description` относится к *операции пути* в целом.
///
/// check | Проверка
/// tip | Совет
OpenAPI указывает, что каждой *операции пути* необходимо описание ответа.
@@ -94,7 +94,7 @@ OpenAPI указывает, что каждой *операции пути* не
{* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *}
Он будет четко помечен как устаревший в интерактивной документации:
Она будет четко помечена как устаревшая в интерактивной документации:
<img src="/img/tutorial/path-operation-configuration/image04.png">
@@ -8,7 +8,7 @@
{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *}
/// info | Информация
/// note | Примечание
Поддержка `Annotated` была добавлена в FastAPI начиная с версии 0.95.0 (и с этой версии рекомендуется использовать этот подход).
@@ -131,7 +131,7 @@ Python не будет ничего делать с `*`, но он будет з
* `lt`: меньше (`l`ess `t`han)
* `le`: меньше или равно (`l`ess than or `e`qual)
/// info | Информация
/// note | Примечание
`Query`, `Path` и другие классы, которые вы разберёте позже, являются наследниками общего класса `Param`.
+4 -4
View File
@@ -20,7 +20,7 @@
Здесь, `item_id` объявлен типом `int`.
/// check | Заметка
/// tip | Подсказка
Это обеспечит поддержку редактора кода внутри функции (проверка ошибок, автозавершение и т.п.).
@@ -34,7 +34,7 @@
{"item_id":3}
```
/// check | Заметка
/// tip | Подсказка
Обратите внимание на значение `3`, которое получила (и вернула) функция. Это целочисленный Python `int`, а не строка `"3"`.
@@ -66,7 +66,7 @@
Та же ошибка возникнет, если вместо `int` передать `float`, например: [http://127.0.0.1:8000/items/4.2](http://127.0.0.1:8000/items/4.2)
/// check | Заметка
/// tip | Подсказка
**FastAPI** обеспечивает валидацию данных, используя всё те же определения типов.
@@ -82,7 +82,7 @@
<img src="/img/tutorial/path-params/image01.png">
/// check | Заметка
/// tip | Подсказка
Ещё раз, просто используя определения типов, **FastAPI** обеспечивает автоматическую интерактивную документацию (с интеграцией Swagger UI).
@@ -29,7 +29,7 @@ FastAPI поймёт, что значение `q` не обязательно,
{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *}
/// info | Дополнительная информация
/// note | Примечание
Поддержка `Annotated` (и рекомендация использовать его) появилась в FastAPI версии 0.95.0.
@@ -80,8 +80,8 @@ q: Annotated[str | None] = None
Теперь FastAPI будет:
* **валидировать** данные, удостоверяясь, что максимальная длина — 50 символов;
* показывать **понятную ошибку** клиенту, если данные невалидны;
* **документировать** параметр в *операции пути* схемы OpenAPI (он будет показан в **UI автоматической документации**).
* отображать **понятную ошибку** клиенту, если данные невалидны;
* **документировать** параметр в *операции пути* схемы OpenAPI (он будет отображаться в **UI автоматической документации**).
## Альтернатива (устаревшее): `Query` как значение по умолчанию { #alternative-old-query-as-the-default-value }
@@ -119,7 +119,7 @@ q: str | None = None
q: str | None = Query(default=None, max_length=50)
```
Это провалидирует данные, покажет понятную ошибку, если данные невалидны, и задокументирует параметр в *операции пути* схемы OpenAPI.
Это провалидирует данные, отобразит понятную ошибку, если данные невалидны, и задокументирует параметр в *операции пути* схемы OpenAPI.
### `Query` как значение по умолчанию или внутри `Annotated` { #query-as-the-default-value-or-in-annotated }
@@ -141,7 +141,7 @@ q: Annotated[str, Query(default="rick")] = "morty"
q: Annotated[str, Query()] = "rick"
```
...или в старой кодовой базе вы увидите:
...или в старых кодовых базах вы увидите:
```Python
q: str = Query(default="rick")
@@ -153,19 +153,19 @@ q: str = Query(default="rick")
**Значение по умолчанию** у **параметра функции** — это **настоящее значение по умолчанию**, что более интуитивно для Python. 😌
Вы можете **вызвать** эту же функцию в **других местах** без FastAPI, и она будет **работать как ожидается**. Если есть **обязательный** параметр (без значения по умолчанию), ваш **редактор** сообщит об ошибке, **Python** тоже пожалуется, если вы запустите её без передачи обязательного параметра.
Вы можете **вызвать** эту же функцию в **других местах** без FastAPI, и она будет **работать как ожидается**. Если есть **обязательный** параметр (без значения по умолчанию), ваш **редактор кода** сообщит об ошибке, **Python** тоже пожалуется, если вы запустите её без передачи обязательного параметра.
Если вы не используете `Annotated`, а применяете **(устаревший) стиль со значением по умолчанию**, то при вызове этой функции без FastAPI в **других местах** вам нужно **помнить** о том, что надо передать аргументы, чтобы всё работало корректно, иначе значения будут не такими, как вы ожидаете (например, вместо `str` будет `QueryInfo` или что-то подобное). И ни редактор, ни Python не будут ругаться при самом вызове функции — ошибка проявится лишь при операциях внутри.
Если вы не используете `Annotated`, а применяете **(устаревший) стиль со значением по умолчанию**, то при вызове этой функции без FastAPI в **других местах** вам нужно **помнить** о том, что надо передать аргументы, чтобы всё работало корректно, иначе значения будут не такими, как вы ожидаете (например, вместо `str` будет `QueryInfo` или что-то подобное). И ни редактор кода, ни Python не будут ругаться при самом вызове функции — ошибка проявится лишь при операциях внутри.
Так как `Annotated` может содержать больше одной аннотации метаданных, теперь вы можете использовать ту же функцию и с другими инструментами, например с [Typer](https://typer.tiangolo.com/). 🚀
## Больше валидаций { #add-more-validations }
## Добавим больше валидаций { #add-more-validations }
Можно также добавить параметр `min_length`:
{* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *}
## Регулярные выражения { #add-regular-expressions }
## Добавим регулярные выражения { #add-regular-expressions }
Вы можете определить <dfn title="Регулярное выражение (regex, regexp) — это последовательность символов, задающая шаблон поиска для строк.">регулярное выражение</dfn> `pattern`, которому должен соответствовать параметр:
@@ -173,7 +173,7 @@ q: str = Query(default="rick")
Данный шаблон регулярного выражения проверяет, что полученное значение параметра:
* `^`: начинается с следующих символов, до них нет символов.
* `^`: начинается со следующих символов, до них нет символов.
* `fixedquery`: имеет точное значение `fixedquery`.
* `$`: заканчивается здесь, после `fixedquery` нет никаких символов.
@@ -191,7 +191,7 @@ q: str = Query(default="rick")
/// note | Примечание
Наличие значения по умолчанию любого типа, включая `None`, делает параметр необязательным.
Наличие значения по умолчанию любого типа, включая `None`, делает параметр необязательным (не обязательным).
///
@@ -243,7 +243,7 @@ http://localhost:8000/items/?q=foo&q=bar
вы получите множественные значения *query-параметров* `q` (`foo` и `bar`) в виде Python-`list` внутри вашей *функции-обработчика пути*, в *параметре функции* `q`.
Таким образом, ответ на этот URL будет:
Таким образом, HTTP-ответом на этот URL будет:
```JSON
{
@@ -276,7 +276,7 @@ http://localhost:8000/items/?q=foo&q=bar
http://localhost:8000/items/
```
значение по умолчанию для `q` будет: `["foo", "bar"]`, и ответом будет:
значение по умолчанию для `q` будет: `["foo", "bar"]`, и вашим HTTP-ответом будет:
```JSON
{
@@ -301,7 +301,7 @@ http://localhost:8000/items/
///
## Больше метаданных { #declare-more-metadata }
## Объявление дополнительных метаданных { #declare-more-metadata }
Можно добавить больше информации о параметре.
@@ -369,7 +369,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems
В таких случаях можно использовать **кастомную функцию-валидатор**, которая применяется после обычной валидации (например, после проверки, что значение — это `str`).
Этого можно добиться, используя [`AfterValidator` Pydantic](https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator) внутри `Annotated`.
Этого можно добиться, используя [Pydantic `AfterValidator`](https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator) внутри `Annotated`.
/// tip | Совет
@@ -377,11 +377,11 @@ http://127.0.0.1:8000/items/?item-query=foobaritems
///
Например, эта кастомная проверка убеждается, что ID элемента начинается с `isbn-` для номера книги <abbr title="International Standard Book Number - Международный стандартный книжный номер">ISBN</abbr> или с `imdb-` для ID URL фильма на <abbr title="Internet Movie Database - Интернетная база данных фильмов: веб‑сайт с информацией о фильмах">IMDB</abbr>:
Например, эта кастомная проверка убеждается, что ID элемента начинается с `isbn-` для номера книги <abbr title="International Standard Book Number - Международный стандартный книжный номер">ISBN</abbr> или с `imdb-` для ID URL фильма в <abbr title="Internet Movie Database - Интернет-база данных фильмов: веб‑сайт с информацией о фильмах">IMDB</abbr>:
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *}
/// info | Дополнительная информация
/// note | Примечание
Это доступно в Pydantic версии 2 и выше. 😎
@@ -391,7 +391,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems
Если вам нужна валидация, требующая общения с каким‑либо **внешним компонентом** — базой данных или другим API — вместо этого используйте **Зависимости FastAPI**, вы познакомитесь с ними позже.
Эти кастомные валидаторы предназначены для проверок, которые можно выполнить, имея **только** те же **данные**, что пришли в запросе.
Эти кастомные валидаторы предназначены для проверок, которые можно выполнить, имея **только** те же **данные**, что пришли в HTTP-запросе.
///
@@ -429,7 +429,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems
Вы можете объявлять дополнительные проверки и метаданные для параметров.
Общие метаданные и настройки:
Общие проверки и метаданные:
* `alias`
* `title`
+29 -28
View File
@@ -1,10 +1,10 @@
# Query-параметры { #query-parameters }
Когда вы объявляете параметры функции, которые не являются параметрами пути, они автоматически интерпретируются как "query"-параметры.
Когда вы объявляете параметры функции, которые не являются частью path-параметров, они автоматически интерпретируются как "query"-параметры.
{* ../../docs_src/query_params/tutorial001_py310.py hl[9] *}
Query-параметры представляют из себя набор пар ключ-значение, которые идут после знака `?` в URL-адресе, разделенные символами `&`.
Query — это набор пар ключ-значение, которые идут после знака `?` в URL-адресе, разделенные символами `&`.
Например, в этом URL-адресе:
@@ -12,25 +12,25 @@ Query-параметры представляют из себя набор па
http://127.0.0.1:8000/items/?skip=0&limit=10
```
...параметры запроса такие:
...query-параметры такие:
* `skip`: со значением `0`
* `limit`: со значением `10`
Будучи частью URL-адреса, они "по умолчанию" являются строками.
Будучи частью URL-адреса, они "естественным образом" являются строками.
Но когда вы объявляете их с использованием типов Python (в примере выше, как `int`), они конвертируются в указанный тип данных и проходят проверку на соответствие ему.
Все те же правила, которые применяются к path-параметрам, также применяются и query-параметрам:
Все те же процессы, которые применяются к path-параметрам, также применяются и к query-параметрам:
* Поддержка от редактора кода (очевидно)
* <dfn title="преобразование строки, полученной из HTTP-запроса в данные Python">"Парсинг"</dfn> данных
* Проверка на соответствие данных (Валидация)
* <dfn title="преобразование строки, полученной из HTTP-запроса, в данные Python">"Парсинг"</dfn> данных
* Валидация данных
* Автоматическая документация
## Значения по умолчанию { #defaults }
Поскольку query-параметры не являются фиксированной частью пути, они могут быть не обязательными и иметь значения по умолчанию.
Поскольку query-параметры не являются фиксированной частью пути, они могут быть необязательными и иметь значения по умолчанию.
В примере выше значения по умолчанию равны `skip=0` и `limit=10`.
@@ -40,13 +40,13 @@ http://127.0.0.1:8000/items/?skip=0&limit=10
http://127.0.0.1:8000/items/
```
будет таким же, как если перейти используя параметры по умолчанию:
будет таким же, как если перейти по:
```
http://127.0.0.1:8000/items/?skip=0&limit=10
```
Но если вы введёте, например:
Но если вы перейдёте, например, по:
```
http://127.0.0.1:8000/items/?skip=20
@@ -55,7 +55,7 @@ http://127.0.0.1:8000/items/?skip=20
Значения параметров в вашей функции будут:
* `skip=20`: потому что вы установили это в URL-адресе
* `limit=10`: т.к это было значение по умолчанию
* `limit=10`: потому что это было значение по умолчанию
## Необязательные параметры { #optional-parameters }
@@ -63,21 +63,21 @@ http://127.0.0.1:8000/items/?skip=20
{* ../../docs_src/query_params/tutorial002_py310.py hl[7] *}
В этом случае, параметр `q` будет не обязательным и будет иметь значение `None` по умолчанию.
В этом случае параметр функции `q` будет необязательным и будет иметь значение `None` по умолчанию.
/// check | Важно
/// tip | Подсказка
Также обратите внимание, что **FastAPI** достаточно умён чтобы заметить, что параметр `item_id` является path-параметром, а `q` нет, поэтому, это параметр запроса.
Также обратите внимание, что **FastAPI** достаточно умён, чтобы заметить, что path-параметр `item_id` является path-параметром, а `q` нет, поэтому это query-параметр.
///
## Преобразование типа параметра запроса { #query-parameter-type-conversion }
## Преобразование типа query-параметра { #query-parameter-type-conversion }
Вы также можете объявлять параметры с типом `bool`, которые будут преобразованы соответственно:
Вы также можете объявлять типы `bool`, и они будут преобразованы:
{* ../../docs_src/query_params/tutorial003_py310.py hl[7] *}
В этом случае, если вы сделаете запрос:
В этом случае, если вы перейдёте по:
```
http://127.0.0.1:8000/items/foo?short=1
@@ -107,11 +107,12 @@ http://127.0.0.1:8000/items/foo?short=on
http://127.0.0.1:8000/items/foo?short=yes
```
или в любом другом варианте написания (в верхнем регистре, с заглавной буквой, и т.п), внутри вашей функции параметр `short` будет иметь значение `True` типа данных `bool` . В противном случае - `False`.
или в любом другом варианте написания (в верхнем регистре, с заглавной буквой и т.п.), внутри вашей функции параметр `short` будет иметь значение `True` типа данных `bool`. В противном случае `False`.
## Смешивание query-параметров и path-параметров { #multiple-path-and-query-parameters }
Вы можете объявлять несколько query-параметров и path-параметров одновременно, **FastAPI** сам разберётся, что чем является.
## Несколько path-параметров и query-параметров { #multiple-path-and-query-parameters }
Вы можете объявлять несколько path-параметров и query-параметров одновременно, **FastAPI** знает, что чем является.
И вы не обязаны объявлять их в каком-либо определенном порядке.
@@ -123,21 +124,21 @@ http://127.0.0.1:8000/items/foo?short=yes
Когда вы объявляете значение по умолчанию для параметра, который не является path-параметром (в этом разделе мы пока что рассмотрели только query-параметры), то он не является обязательным.
Если вы не хотите задавать конкретное значение, но хотите сделать параметр необязательным, вы можете установить значение по умолчанию равным `None`.
Если вы не хотите задавать конкретное значение, но хотите просто сделать параметр необязательным, установите значение по умолчанию равным `None`.
Но если вы хотите сделать query-параметр обязательным, вы можете просто не указывать значение по умолчанию:
{* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *}
Здесь параметр запроса `needy` является обязательным параметром с типом данных `str`.
Здесь query-параметр `needy` является обязательным query-параметром с типом данных `str`.
Если вы откроете в браузере URL-адрес, например:
Если вы откроете в браузере URL-адрес вроде:
```
http://127.0.0.1:8000/items/foo-item
```
...без добавления обязательного параметра `needy`, вы увидите подобного рода ошибку:
...без добавления обязательного параметра `needy`, вы увидите ошибку вроде:
```JSON
{
@@ -170,18 +171,18 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
}
```
Конечно, вы можете определить некоторые параметры как обязательные, некоторые — со значением по умолчанию, а некоторые — полностью необязательные:
И, конечно, вы можете определить некоторые параметры как обязательные, некоторые — со значением по умолчанию, а некоторые — полностью необязательные:
{* ../../docs_src/query_params/tutorial006_py310.py hl[8] *}
В этом примере, у нас есть 3 параметра запроса:
В этом случае есть 3 query-параметра:
* `needy`, обязательный `str`.
* `skip`, типа `int` и со значением по умолчанию `0`.
* `skip`, `int` со значением по умолчанию `0`.
* `limit`, необязательный `int`.
/// tip | Подсказка
Вы можете использовать класс `Enum` также, как ранее применяли его с [Path-параметрами](path-params.md#predefined-values).
Вы можете использовать `Enum` так же, как ранее применяли его с [Path-параметрами](path-params.md#predefined-values).
///
+15 -16
View File
@@ -2,7 +2,7 @@
Используя класс `File`, мы можем позволить клиентам загружать файлы.
/// info | Дополнительная информация
/// note | Примечание
Чтобы получать загруженные файлы, сначала установите [`python-multipart`](https://github.com/Kludex/python-multipart).
@@ -28,7 +28,7 @@ $ pip install python-multipart
{* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *}
/// info | Дополнительная информация
/// note | Примечание
`File` - это класс, который наследуется непосредственно от `Form`.
@@ -38,13 +38,13 @@ $ pip install python-multipart
/// tip | Подсказка
Для объявления тела файла необходимо использовать `File`, поскольку в противном случае параметры будут интерпретироваться как параметры запроса или параметры тела (JSON).
Чтобы объявить файлы в теле запроса, необходимо использовать `File`, поскольку иначе параметры будут интерпретироваться как параметры запроса или body-параметры (JSON).
///
Файлы будут загружены как данные формы.
Если вы объявите тип параметра у *функции операции пути* как `bytes`, то **FastAPI** прочитает файл за вас, и вы получите его содержимое в виде `bytes`.
Если вы объявите тип параметра у *функции-обработчика пути* как `bytes`, то **FastAPI** прочитает файл за вас, и вы получите его содержимое в виде `bytes`.
Следует иметь в виду, что все содержимое будет храниться в памяти. Это хорошо подходит для небольших файлов.
@@ -64,15 +64,15 @@ $ pip install python-multipart
* Это означает, что он будет хорошо работать с большими файлами, такими как изображения, видео, большие бинарные файлы и т.д., не потребляя при этом всю память.
* Из загруженного файла можно получить метаданные.
* Он реализует [file-like](https://docs.python.org/3/glossary.html#term-file-like-object) `async` интерфейс.
* Он предоставляет реальный объект Python [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile), который вы можете передать непосредственно другим библиотекам, которые ожидают файл в качестве объекта.
* Он предоставляет реальный объект Python [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile), который вы можете передать непосредственно другим библиотекам, которые ожидают file-like объект.
### `UploadFile` { #uploadfile }
`UploadFile` имеет следующие атрибуты:
* `filename`: Строка `str` с исходным именем файла, который был загружен (например, `myimage.jpg`).
* `content_type`: Строка `str` с типом содержимого (MIME type / media type) (например, `image/jpeg`).
* `file`: [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) (a [file-like](https://docs.python.org/3/glossary.html#term-file-like-object) объект). Это фактический файл Python, который можно передавать непосредственно другим функциям или библиотекам, ожидающим файл в качестве объекта.
* `content_type`: Строка `str` с типом содержимого (MIME-тип / тип содержимого) (например, `image/jpeg`).
* `file`: [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) ([file-like](https://docs.python.org/3/glossary.html#term-file-like-object) объект). Это фактический файл Python, который можно передавать непосредственно другим функциям или библиотекам, ожидающим file-like объект.
`UploadFile` имеет следующие методы `async`. Все они вызывают соответствующие файловые методы (используя внутренний `SpooledTemporaryFile`).
@@ -85,19 +85,18 @@ $ pip install python-multipart
Поскольку все эти методы являются `async` методами, вам следует использовать "await" вместе с ними.
Например, внутри `async` *функции операции пути* можно получить содержимое с помощью:
Например, внутри `async` *функции-обработчика пути* можно получить содержимое с помощью:
```Python
contents = await myfile.read()
```
Если вы находитесь внутри обычной `def` *функции операции пути*, можно получить прямой доступ к файлу `UploadFile.file`, например:
Если вы находитесь внутри обычной `def` *функции-обработчика пути*, можно получить прямой доступ к файлу `UploadFile.file`, например:
```Python
contents = myfile.file.read()
```
/// note | Технические детали `async`
При использовании методов `async` **FastAPI** запускает файловые методы в пуле потоков и ожидает их.
@@ -106,7 +105,7 @@ contents = myfile.file.read()
/// note | Технические детали Starlette
**FastAPI** наследует `UploadFile` непосредственно из **Starlette**, но добавляет некоторые детали для совместимости с **Pydantic** и другими частями FastAPI.
`UploadFile` из **FastAPI** наследуется непосредственно от `UploadFile` из **Starlette**, но добавляет некоторые необходимые части для совместимости с **Pydantic** и другими частями FastAPI.
///
@@ -118,17 +117,17 @@ contents = myfile.file.read()
/// note | Технические детали
Данные из форм обычно кодируются с использованием "media type" `application/x-www-form-urlencoded` когда он не включает файлы.
Данные из форм обычно кодируются с использованием типа содержимого `application/x-www-form-urlencoded`, когда они не включают файлы.
Но когда форма включает файлы, она кодируется как `multipart/form-data`. Если вы используете `File`, **FastAPI** будет знать, что ему нужно получить файлы из нужной части тела.
Но когда форма включает файлы, она кодируется как `multipart/form-data`. Если вы используете `File`, **FastAPI** будет знать, что ему нужно получить файлы из нужной части тела запроса.
Если вы хотите узнать больше об этих кодировках и полях форм, перейдите по ссылке [<abbr title="Mozilla Developer Network - Сеть разработчиков Mozilla">MDN</abbr> web docs for `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST).
Если вы хотите узнать больше об этих кодировках и полях форм, перейдите к [веб-документации <abbr title="Mozilla Developer Network - Сеть разработчиков Mozilla">MDN</abbr> по `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST).
///
/// warning | Внимание
В операции *функции операции пути* можно объявить несколько параметров `File` и `Form`, но нельзя также объявлять поля `Body`, которые предполагается получить в виде JSON, поскольку тело запроса будет закодировано с помощью `multipart/form-data`, а не `application/json`.
В *операции пути* можно объявить несколько параметров `File` и `Form`, но нельзя также объявлять поля `Body`, которые предполагается получить в виде JSON, поскольку HTTP-запрос будет иметь тело, закодированное с помощью `multipart/form-data`, а не `application/json`.
Это не является ограничением **FastAPI**, это часть протокола HTTP.
@@ -174,4 +173,4 @@ contents = myfile.file.read()
## Резюме { #recap }
Используйте `File`, `bytes` и `UploadFile` для работы с файлами, которые будут загружаться и передаваться в виде данных формы.
Используйте `File`, `bytes` и `UploadFile`, чтобы объявлять файлы для загрузки в HTTP-запросе, передаваемые как данные формы.
+1 -1
View File
@@ -2,7 +2,7 @@
Вы можете использовать **Pydantic-модели** для объявления **полей формы** в FastAPI.
/// info | Дополнительная информация
/// note | Заметка
Чтобы использовать формы, сначала установите [`python-multipart`](https://github.com/Kludex/python-multipart).
@@ -2,7 +2,7 @@
Вы можете определять файлы и поля формы одновременно, используя `File` и `Form`.
/// info | Информация
/// note | Примечание
Чтобы получать загруженные файлы и/или данные форм, сначала установите [`python-multipart`](https://github.com/Kludex/python-multipart).
+3 -2
View File
@@ -1,8 +1,9 @@
# Данные формы { #form-data }
Когда вам нужно получить поля формы вместо JSON, вы можете использовать `Form`.
/// info | Дополнительная информация
/// note | Примечание
Чтобы использовать формы, сначала установите [`python-multipart`](https://github.com/Kludex/python-multipart).
@@ -32,7 +33,7 @@ $ pip install python-multipart
С помощью `Form` вы можете объявить те же настройки, что и с `Body``Query`, `Path`, `Cookie`), включая валидацию, примеры, псевдоним (например, `user-name` вместо `username`) и т.д.
/// info | Дополнительная информация
/// note | Примечание
`Form` — это класс, который наследуется непосредственно от `Body`.
+4 -4
View File
@@ -72,11 +72,11 @@ FastAPI будет использовать этот `response_model` для д
{* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *}
/// info | Информация
/// note | Примечание
Чтобы использовать `EmailStr`, сначала установите [`email-validator`](https://github.com/JoshData/python-email-validator).
Убедитесь, что вы создали [виртуальное окружение](../virtual-environments.md), активировали его, а затем установите пакет, например:
Убедитесь, что вы создали [виртуальное окружение](../virtual-environments.md), активировали его, а затем установили пакет, например:
```console
$ pip install email-validator
@@ -178,7 +178,7 @@ FastAPI делает несколько вещей внутри вместе с
## Другие аннотации возвращаемых типов { #other-return-type-annotations }
Бывают случаи, когда вы возвращаете что-то, что не является валидным полем Pydantic, и аннотируете это в функции только ради поддержки инструментов (редактор кода, mypy и т.д.).
Бывают случаи, когда вы возвращаете что-то, что не является валидным полем Pydantic, и аннотируете это в функции только ради поддержки инструментов (редактор коды, mypy и т.д.).
### Возврат Response напрямую { #return-a-response-directly }
@@ -251,7 +251,7 @@ FastAPI делает несколько вещей внутри вместе с
}
```
/// info | Информация
/// note | Примечание
Вы также можете использовать:
+13 -13
View File
@@ -1,6 +1,6 @@
# Статус-код ответа { #response-status-code }
Подобно тому, как вы можете задать модель/схему ответа, вы можете объявить HTTP статус-код, используемый для ответа, с помощью параметра `status_code` в любой из *операций пути*:
Подобно тому, как вы можете задать модель ответа, вы можете объявить HTTP статус-код, используемый для ответа, с помощью параметра `status_code` в любой из *операций пути*:
* `@app.get()`
* `@app.post()`
@@ -18,7 +18,7 @@
Параметр `status_code` принимает число, обозначающее HTTP статус-код.
/// info | Информация
/// note | Примечание
В качестве значения параметра `status_code` также может использоваться `IntEnum`, например, из библиотеки [`http.HTTPStatus`](https://docs.python.org/3/library/http.html#http.HTTPStatus) в Python.
@@ -26,8 +26,8 @@
Это позволит:
* Возвращать указанный код статуса в ответе.
* Документировать его как код статуса ответа в OpenAPI схеме (а значит, и в пользовательских интерфейсах):
* Возвращать указанный статус-код в ответе.
* Документировать его как статус-код ответа в OpenAPI схеме (а значит, и в пользовательских интерфейсах):
<img src="/img/tutorial/response-status-code/image01.png">
@@ -47,26 +47,26 @@ FastAPI знает об этом и создаст документацию Open
///
В протоколе HTTP числовой код состояния из 3 цифр отправляется как часть ответа.
В протоколе HTTP числовой статус-код из 3 цифр отправляется как часть ответа.
У кодов статуса есть названия, чтобы упростить их распознавание, но важны именно числовые значения.
У статус-кодов есть названия, чтобы упростить их распознавание, но важны именно числовые значения.
Кратко:
* `100 - 199` – статус-коды информационного типа. Они редко используются разработчиками напрямую. Ответы с этими кодами не могут иметь тела.
* `100 - 199` – статус-коды информационного типа. Они редко используются разработчиками напрямую. Ответы с этими статус-кодами не могут иметь тела.
* **`200 - 299`** – статус-коды, сообщающие об успешной обработке запроса. Они используются чаще всего.
* `200` это код статуса ответа по умолчанию, который означает, что все прошло "OK".
* `200` это статус-код по умолчанию, который означает, что все прошло "OK".
* Другим примером может быть статус `201`, "Created". Он обычно используется после создания новой записи в базе данных.
* Особый случай – `204`, "No Content". Этот статус ответа используется, когда нет содержимого для возврата клиенту, и поэтому ответ не должен иметь тела.
* **`300 - 399`** – статус-коды, сообщающие о перенаправлениях. Ответы с этими кодами статуса могут иметь или не иметь тело, за исключением ответов со статусом `304`, "Not Modified", у которых не должно быть тела.
* **`300 - 399`** – статус-коды, сообщающие о перенаправлениях. Ответы с этими статус-кодами могут иметь или не иметь тело, за исключением ответов со статусом `304`, "Not Modified", у которых не должно быть тела.
* **`400 - 499`** – статус-коды, сообщающие о клиентской ошибке. Это ещё одна наиболее часто используемая категория.
* Пример код `404` для статуса "Not Found".
* Для общих ошибок со стороны клиента можно просто использовать код `400`.
* `500 - 599` – статус-коды, сообщающие о серверной ошибке. Они почти никогда не используются разработчиками напрямую. Когда что-то идет не так в какой-то части кода вашего приложения или на сервере, он автоматически вернёт один из этих кодов статуса.
* `500 - 599` – статус-коды, сообщающие о серверной ошибке. Они почти никогда не используются разработчиками напрямую. Когда что-то идет не так в какой-то части кода вашего приложения или на сервере, он автоматически вернёт один из этих статус-кодов.
/// tip | Подсказка
Чтобы узнать больше о HTTP кодах статуса и о том, для чего каждый из них предназначен, ознакомьтесь с [<abbr title="Mozilla Developer Network - Сеть разработчиков Mozilla">MDN</abbr> документацией об HTTP статус-кодах](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status).
Чтобы узнать больше о HTTP статус-кодах и о том, для чего каждый из них предназначен, ознакомьтесь с [<abbr title="Mozilla Developer Network - Сеть разработчиков Mozilla">MDN</abbr> документацией об HTTP статус-кодах](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status).
///
@@ -76,7 +76,7 @@ FastAPI знает об этом и создаст документацию Open
{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *}
`201` это код статуса "Создано".
`201` это статус-код для "Created".
Но вам не обязательно запоминать, что означает каждый из этих кодов.
@@ -84,7 +84,7 @@ FastAPI знает об этом и создаст документацию Open
{* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *}
Они содержат те же числовые значения, но позволяют использовать автозавершение редактора кода для выбора кода статуса:
Они существуют только для удобства, содержат те же числовые значения, но позволяют использовать автозавершение редактора кода для выбора статус-кода:
<img src="/img/tutorial/response-status-code/image02.png">
@@ -1,4 +1,4 @@
# Объявление примеров данных запроса { #declare-request-example-data }
# Объявление примеров данных HTTP-запроса { #declare-request-example-data }
Вы можете объявлять примеры данных, которые ваше приложение может получать.
@@ -12,7 +12,7 @@
Эта дополнительная информация будет добавлена как есть в выходную **JSON Schema** этой модели и будет использоваться в документации API.
Вы можете использовать атрибут `model_config`, который принимает `dict`, как описано в [Документация Pydantic: Конфигурация](https://docs.pydantic.dev/latest/api/config/).
Вы можете использовать атрибут `model_config`, который принимает `dict`, как описано в [документации Pydantic: Конфигурация](https://docs.pydantic.dev/latest/api/config/).
Вы можете задать `"json_schema_extra"` с `dict`, содержащим любые дополнительные данные, которые вы хотите видеть в сгенерированной JSON Schema, включая `examples`.
@@ -24,9 +24,9 @@
///
/// info | Информация
/// note | Примечание
OpenAPI 3.1.0 (используется начиная с FastAPI 0.99.0) добавил поддержку `examples`, который является частью стандарта **JSON Schema**.
OpenAPI 3.1.0 (используется начиная с FastAPI 0.99.0) добавил поддержку `examples`, которое является частью стандарта **JSON Schema**.
До этого поддерживалось только ключевое слово `example` с одним примером. Оно всё ещё поддерживается в OpenAPI 3.1.0, но помечено как устаревшее и не является частью стандарта JSON Schema. Поэтому рекомендуется мигрировать `example` на `examples`. 🤓
@@ -80,13 +80,13 @@ OpenAPI 3.1.0 (используется начиная с FastAPI 0.99.0) доб
Ещё до того как **JSON Schema** поддержала `examples`, в OpenAPI была поддержка другого поля, также называемого `examples`.
Эти **специфические для OpenAPI** `examples` находятся в другой секции спецификации OpenAPI. Они находятся в **подробностях для каждой операции пути (обработчика пути)**, а не внутри каждого объекта Schema.
Эти **специфические для OpenAPI** `examples` находятся в другой секции спецификации OpenAPI. Они находятся в **подробностях каждой *операции пути***, а не внутри каждой JSON Schema.
И Swagger UI уже какое‑то время поддерживает именно это поле `examples`. Поэтому вы можете использовать его, чтобы **отобразить** разные **примеры в UI документации**.
Структура этого специфичного для OpenAPI поля `examples` — это `dict` с **несколькими примерами** (вместо `list`), каждый с дополнительной информацией, которая также будет добавлена в **OpenAPI**.
Это не помещается внутрь каждого объекта Schema в OpenAPI, это находится снаружи, непосредственно на уровне самой *операции пути*.
Это не помещается внутрь каждой JSON Schema, содержащейся в OpenAPI, это находится снаружи, непосредственно на уровне самой *операции пути*.
### Использование параметра `openapi_examples` { #using-the-openapi-examples-parameter }
@@ -155,7 +155,7 @@ OpenAPI также добавила поля `example` и `examples` в друг
* `File()`
* `Form()`
/// info | Информация
/// note | Примечание
Этот старый специфичный для OpenAPI параметр `examples` теперь называется `openapi_examples`, начиная с FastAPI `0.103.0`.
@@ -171,7 +171,7 @@ OpenAPI также добавила поля `example` и `examples` в друг
Это новое поле `examples` в JSON Schema — это **просто `list`** примеров, а не dict с дополнительными метаданными, как в других местах OpenAPI (описанных выше).
/// info | Информация
/// note | Примечание
Даже после того как OpenAPI 3.1.0 была выпущена с этой новой, более простой интеграцией с JSON Schema, какое‑то время Swagger UI, инструмент, предоставляющий автоматическую документацию, не поддерживал OpenAPI 3.1.0 (поддержка появилась начиная с версии 5.0.0 🎉).
@@ -24,7 +24,7 @@
## Запуск { #run-it }
/// info | Дополнительная информация
/// note | Примечание
Пакет [`python-multipart`](https://github.com/Kludex/python-multipart) автоматически устанавливается вместе с **FastAPI**, если вы запускаете команду `pip install "fastapi[standard]"`.
@@ -60,7 +60,7 @@ $ fastapi dev
<img src="/img/tutorial/security/image01.png">
/// check | Кнопка авторизации!
/// tip | Кнопка авторизации!
У вас уже появилась новая кнопка «Authorize».
@@ -118,7 +118,7 @@ OAuth2 был спроектирован так, чтобы бэкенд или
В этом примере мы будем использовать **OAuth2**, с потоком **Password**, используя токен **Bearer**. Для этого мы используем класс `OAuth2PasswordBearer`.
/// info | Дополнительная информация
/// note | Примечание
Токен «bearer» — не единственный вариант.
@@ -148,7 +148,7 @@ OAuth2 был спроектирован так, чтобы бэкенд или
Скоро мы также создадим и саму операцию пути.
/// info | Дополнительная информация
/// note | Примечание
Если вы очень строгий «питонист», вам может не понравиться стиль имени параметра `tokenUrl` вместо `token_url`.
@@ -176,7 +176,7 @@ oauth2_scheme(some, parameters)
**FastAPI** будет знать, что может использовать эту зависимость для определения «схемы безопасности» в схеме OpenAPI (и в автоматической документации по API).
/// info | Технические детали
/// note | Технические детали
**FastAPI** будет знать, что может использовать класс `OAuth2PasswordBearer` (объявленный в зависимости) для определения схемы безопасности в OpenAPI, потому что он наследуется от `fastapi.security.oauth2.OAuth2`, который, в свою очередь, наследуется от `fastapi.security.base.SecurityBase`.
@@ -186,9 +186,9 @@ oauth2_scheme(some, parameters)
## Что он делает { #what-it-does }
Он будет искать в запросе заголовок `Authorization`, проверять, что его значение — это `Bearer ` плюс некоторый токен, и вернет токен как `str`.
Он будет искать в HTTP-запросе HTTP-заголовок `Authorization`, проверять, что его значение — это `Bearer ` плюс некоторый токен, и вернет токен как `str`.
Если заголовок `Authorization` отсутствует или его значение не содержит токен `Bearer `, он сразу ответит ошибкой со статус-кодом 401 (`UNAUTHORIZED`).
Если HTTP-заголовок `Authorization` отсутствует или его значение не содержит токен `Bearer `, он сразу ответит ошибкой со статус-кодом 401 (`UNAUTHORIZED`).
Вам даже не нужно проверять наличие токена, чтобы вернуть ошибку. Вы можете быть уверены: если ваша функция была выполнена, в этом токене будет `str`.
@@ -14,7 +14,7 @@
Точно так же, как мы используем Pydantic для объявления тел запросов, мы можем использовать его где угодно:
{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *}
{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *}
## Создать зависимость `get_current_user` { #create-a-get-current-user-dependency }
@@ -30,7 +30,7 @@
## Получить пользователя { #get-the-user }
`get_current_user` будет использовать созданную нами (ненастоящую) служебную функцию, которая принимает токен типа `str` и возвращает нашу Pydantic-модель `User`:
`get_current_user` будет использовать созданную нами (ненастоящую) вспомогательную функцию, которая принимает токен типа `str` и возвращает нашу Pydantic-модель `User`:
{* ../../docs_src/security/tutorial002_an_py310.py hl[19:22,26:27] *}
@@ -52,9 +52,9 @@
///
/// check | Заметка
/// tip | Подсказка
То, как устроена эта система зависимостей, позволяет иметь разные зависимости, которые возвращают модель `User`.
То, как устроена эта система зависимостей, позволяет иметь разные зависимости (разные "dependables"), которые все возвращают модель `User`.
Мы не ограничены наличием только одной зависимости, которая может возвращать такой тип данных.
@@ -78,7 +78,7 @@
## Размер кода { #code-size }
Этот пример может показаться многословным. Имейте в виду, что в одном файле мы смешиваем безопасность, модели данных, служебные функции и *операции пути*.
Этот пример может показаться многословным. Имейте в виду, что в одном файле мы смешиваем безопасность, модели данных, вспомогательные функции и *операции пути*.
Но вот ключевой момент.
+13 -13
View File
@@ -28,7 +28,7 @@ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4
## Установка `PyJWT` { #install-pyjwt }
Нам необходимо установить `pyjwt` для генерации и проверки JWT-токенов на языке Python.
Нам необходимо установить `PyJWT` для генерации и проверки JWT-токенов на языке Python.
Убедитесь, что вы создали [виртуальное окружение](../../virtual-environments.md), активируйте его, а затем установите `pyjwt`:
@@ -42,7 +42,7 @@ $ pip install pyjwt
</div>
/// info | Дополнительная информация
/// note | Примечание
Если вы планируете использовать алгоритмы цифровой подписи, такие как RSA или ECDSA, вам следует установить зависимость библиотеки криптографии `pyjwt[crypto]`.
@@ -110,9 +110,9 @@ pwdlib также поддерживает алгоритм хешировани
///
Создайте служебную функцию для хэширования пароля, поступающего от пользователя.
Создайте вспомогательную функцию для хэширования пароля, поступающего от пользователя.
А затем создайте другую — для проверки соответствия полученного пароля и хранимого хэша.
А затем создайте другую вспомогательную функцию — для проверки соответствия полученного пароля и хранимого хэша.
И еще одну — для аутентификации и возврата пользователя.
@@ -120,15 +120,15 @@ pwdlib также поддерживает алгоритм хешировани
Когда `authenticate_user` вызывается с именем пользователя, которого нет в базе данных, мы все равно запускаем `verify_password` с использованием фиктивного хэша.
Это гарантирует, что эндпоинт отвечает примерно за одно и то же время вне зависимости от того, существует имя пользователя или нет, предотвращая тайминговые атаки (атака по времени), с помощью которых можно было бы перечислять существующие имена пользователей.
Это гарантирует, что эндпоинт отвечает примерно за одно и то же время вне зависимости от того, существует имя пользователя или нет, предотвращая **тайминговые атаки** (атаки по времени), с помощью которых можно было бы перечислять существующие имена пользователей.
/// note | Технические детали
/// note | Примечание
Если проверить новую (фальшивую) базу данных `fake_users_db`, то можно увидеть, как теперь выглядит хэшированный пароль: `"$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc"`.
///
## Работа с JWT токенами { #handle-jwt-tokens }
## Работа с JWT-токенами { #handle-jwt-tokens }
Импортируйте установленные модули.
@@ -154,7 +154,7 @@ $ openssl rand -hex 32
Определите Pydantic-модель, которая будет использоваться для формирования ответа на запрос на получение токена.
Создайте служебную функцию для генерации нового токена доступа.
Создайте вспомогательную функцию для генерации нового токена доступа.
{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,82:90] *}
@@ -172,7 +172,7 @@ $ openssl rand -hex 32
Создайте `timedelta` со временем истечения срока действия токена.
Создайте реальный токен доступа JWT и верните его
Создайте реальный токен доступа JWT и верните его.
{* ../../docs_src/security/tutorial004_an_py310.py hl[121:136] *}
@@ -188,13 +188,13 @@ JWT может использоваться и для других целей,
Затем вы могли бы добавить права доступа к этой сущности, например "управлять" (для автомобиля) или "редактировать" (для блога).
Затем вы могли бы передать этот JWT-токен пользователю (или боту), и они использовали бы его для выполнения определенных действий (управление автомобилем или редактирование запись в блоге), даже не имея учетной записи, просто используя JWT-токен, сгенерированный вашим API.
Затем вы могли бы передать этот JWT-токен пользователю (или боту), и они использовали бы его для выполнения определенных действий (управление автомобилем или редактирование записи в блоге), даже не имея учетной записи, просто используя JWT-токен, сгенерированный вашим API.
Используя эти идеи, JWT можно применять для гораздо более сложных сценариев.
В отдельных случаях несколько сущностей могут иметь один и тот же идентификатор, скажем, `foo` (пользователь `foo`, автомобиль `foo` и запись в блоге `foo`).
Поэтому, чтобы избежать коллизий идентификаторов, при создании JWT-токена для пользователя можно добавить префикс `username` к значению ключа `sub`. Таким образом, в данном примере значение `sub` было бы `username:johndoe`.
Поэтому, чтобы избежать коллизий идентификаторов, при создании JWT-токена для пользователя можно добавить префикс `username:` к значению ключа `sub`. Таким образом, в данном примере значение `sub` могло бы быть: `username:johndoe`.
Важно помнить, что ключ `sub` должен иметь уникальный идентификатор для всего приложения и представлять собой строку.
@@ -213,7 +213,7 @@ JWT может использоваться и для других целей,
Username: `johndoe`
Password: `secret`
/// check | Проверка
/// tip | Подсказка
Обратите внимание, что нигде в коде не используется открытый текст пароля "`secret`", мы используем только его хэшированную версию.
@@ -238,7 +238,7 @@ Password: `secret`
<img src="/img/tutorial/security/image10.png">
/// note | Техническая информация
/// note | Примечание
Обратите внимание на HTTP-заголовок `Authorization`, значение которого начинается с `Bearer `.
+11 -11
View File
@@ -14,7 +14,7 @@ OAuth2 определяет, что при использовании "password
А ваши модели баз данных могут использовать любые другие имена.
Но для логин-операции пути нам нужно использовать именно эти имена, чтобы быть совместимыми со спецификацией (и иметь возможность, например, использовать встроенную систему документации API).
Но для *операции пути* входа в систему нам нужно использовать именно эти имена, чтобы быть совместимыми со спецификацией (и иметь возможность, например, использовать встроенную систему документации API).
В спецификации также указано, что `username` и `password` должны передаваться в виде данных формы (так что никакого JSON здесь нет).
@@ -32,7 +32,7 @@ OAuth2 определяет, что при использовании "password
* `instagram_basic` используется Facebook / Instagram.
* `https://www.googleapis.com/auth/drive` используется Google.
/// info | Дополнительная информация
/// note | Примечание
В OAuth2 "scope" — это просто строка, которая указывает требуемое конкретное разрешение.
Не имеет значения, содержит ли она другие символы, например `:`, или является ли это URL.
@@ -68,7 +68,7 @@ OAuth2 определяет, что при использовании "password
* Необязательное поле `client_id` (в нашем примере оно не нужно).
* Необязательное поле `client_secret` (в нашем примере оно не нужно).
/// info | Дополнительная информация
/// note | Примечание
`OAuth2PasswordRequestForm` — это не специальный класс для **FastAPI**, как `OAuth2PasswordBearer`.
`OAuth2PasswordBearer` сообщает **FastAPI**, что это схема безопасности. Поэтому она добавляется в OpenAPI соответствующим образом.
@@ -88,7 +88,7 @@ OAuth2 определяет, что при использовании "password
Теперь получим данные о пользователе из (ненастоящей) базы данных, используя `username` из поля формы.
Если такого пользователя нет, то мы возвращаем ошибку "Incorrect username or password" (неверное имя пользователя или пароль).
Если такого пользователя нет, то мы возвращаем ошибку "Incorrect username or password".
Для ошибки используем исключение `HTTPException`:
@@ -136,13 +136,13 @@ UserInDB(
)
```
/// info | Дополнительная информация
Более полное объяснение `**user_dict` можно найти в [документации к **Дополнительным моделям**](../extra-models.md#about-user-in-dict).
/// note | Примечание
Более полное объяснение `**user_dict` можно найти в [документации к **Дополнительным моделям**](../extra-models.md#about-user-in-model-dump).
///
## Возврат токена { #return-the-token }
Ответ операции пути `/token` должен быть объектом JSON.
Ответ эндпоинта `token` должен быть объектом JSON.
В нём должен быть `token_type`. В нашем случае, поскольку мы используем токены типа "Bearer", тип токена должен быть `bearer`.
@@ -151,7 +151,7 @@ UserInDB(
В этом простом примере мы намеренно поступим небезопасно и вернём тот же `username` в качестве токена.
/// tip | Подсказка
В следующей главе вы увидите реальную защищённую реализацию с хешированием паролей и токенами <abbr title="JSON Web Tokens JSON веб-токены">JWT</abbr>.
В следующей главе вы увидите реальную защищённую реализацию с хешированием паролей и токенами <abbr title="JSON Web Tokens - JSON веб-токены">JWT</abbr>.
Но пока давайте сосредоточимся на необходимых нам деталях.
///
@@ -182,7 +182,7 @@ UserInDB(
{* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *}
/// info | Дополнительная информация
/// note | Примечание
Дополнительный HTTP-заголовок `WWW-Authenticate` со значением `Bearer`, который мы здесь возвращаем, также является частью спецификации.
Любой HTTP статус-код 401 "UNAUTHORIZED" должен также возвращать заголовок `WWW-Authenticate`.
@@ -266,8 +266,8 @@ UserInDB(
Теперь у вас есть инструменты для реализации полноценной системы безопасности на основе `username` и `password` для вашего API.
Используя эти средства, можно сделать систему безопасности совместимой с любой базой данных и с любой пользовательской или моделью данных.
Используя эти средства, можно сделать систему безопасности совместимой с любой базой данных и с любой моделью пользователя или моделью данных.
Единственная деталь, которой не хватает, — система пока ещё не "защищена" по-настоящему.
В следующей главе вы увидите, как использовать библиотеку безопасного хеширования паролей и токены <abbr title="JSON Web Tokens JSON веб-токены">JWT</abbr>.
В следующей главе вы увидите, как использовать библиотеку безопасного хеширования паролей и токены <abbr title="JSON Web Tokens - JSON веб-токены">JWT</abbr>.
+3 -3
View File
@@ -4,7 +4,7 @@
Это похоже на [Стриминг JSON Lines](stream-json-lines.md), но использует формат `text/event-stream`, который нативно поддерживается браузерами через [`EventSource` API](https://developer.mozilla.org/en-US/docs/Web/API/EventSource).
/// info | Информация
/// note | Примечание
Добавлено в FastAPI 0.135.0.
@@ -29,7 +29,7 @@ SSE часто используют для стриминга ответов И
/// tip | Совет
Если вам нужно стримить бинарные данные, например видео или аудио, посмотрите расширенное руководство: [Stream Data](../advanced/stream-data.md).
Если вам нужно стримить бинарные данные, например видео или аудио, посмотрите расширенное руководство: [Потоковая передача данных](../advanced/stream-data.md).
///
@@ -113,7 +113,7 @@ SSE работает с любым HTTP-методом, не только с `GE
FastAPI из коробки реализует некоторые лучшие практики для SSE.
- Отправлять комментарий «ping» для поддержания соединения («keep alive») каждые 15 секунд, когда нет сообщений, чтобы предотвратить закрытие соединения некоторыми прокси, как рекомендовано в [HTML specification: Server-Sent Events](https://html.spec.whatwg.org/multipage/server-sent-events.html#authoring-notes).
- Отправлять комментарий «ping» для поддержания соединения («keep alive») каждые 15 секунд, когда нет сообщений, чтобы предотвратить закрытие соединения некоторыми прокси, как рекомендовано в [Спецификация HTML: Server-Sent Events](https://html.spec.whatwg.org/multipage/server-sent-events.html#authoring-notes).
- Устанавливать заголовок `Cache-Control: no-cache`, чтобы предотвратить кэширование потока.
- Устанавливать специальный заголовок `X-Accel-Buffering: no`, чтобы предотвратить буферизацию в некоторых прокси, например Nginx.
+3 -3
View File
@@ -1,6 +1,6 @@
# SQL (реляционные) базы данных { #sql-relational-databases }
**FastAPI** не требует использовать SQL (реляционную) базу данных. Но вы можете использовать любую базу данных, которую хотите.
**FastAPI** не требует использовать SQL (реляционную) базу данных. Но вы можете использовать **любую базу данных**, которую хотите.
Здесь мы рассмотрим пример с использованием [SQLModel](https://sqlmodel.tiangolo.com/).
@@ -8,7 +8,7 @@
/// tip | Подсказка
Вы можете использовать любую другую библиотеку для работы с SQL или NoSQL базами данных (иногда их называют <abbr title="Object Relational Mapper - Объектно-реляционный маппер: термин для библиотеки, где некоторые классы представляют SQL-таблицы, а экземпляры представляют строки в этих таблицах">"ORMs"</abbr>), FastAPI ничего не навязывает. 😎
Вы можете использовать любую другую библиотеку для работы с SQL или NoSQL базами данных (иногда их называют <abbr title="Object Relational Mapper - Объектно-реляционный маппер: красивый термин для библиотеки, где некоторые классы представляют SQL-таблицы, а экземпляры представляют строки в этих таблицах">"ORMs"</abbr>), FastAPI ничего не навязывает. 😎
///
@@ -119,7 +119,7 @@ $ pip install sqlmodel
Так как каждая модель SQLModel также является моделью Pydantic, вы можете использовать её в тех же **аннотациях типов**, в которых используете модели Pydantic.
Например, если вы объявите параметр типа `Hero`, он будет прочитан из **JSON body (тела запроса)**.
Например, если вы объявите параметр типа `Hero`, он будет прочитан из **JSON-тела запроса**.
Аналогично вы можете объявить её как **тип возвращаемого значения** функции, и тогда форма данных отобразится в автоматически сгенерированном UI документации API.
+9 -2
View File
@@ -2,6 +2,14 @@
Вы можете предоставлять статические файлы автоматически из директории, используя `StaticFiles`.
/// tip | Совет
Если вам нужно разместить фронтенд, используйте вместо этого `app.frontend()`, подробнее читайте в разделе [Фронтенд](frontend.md).
`app.frontend()` использует `StaticFiles` под капотом, с несколькими дополнительными преимуществами для фронтендов, такими как обработка маршрутизации на стороне клиента.
///
## Использование `StaticFiles` { #use-staticfiles }
* Импортируйте `StaticFiles`.
@@ -21,8 +29,7 @@
"Монтирование" означает добавление полноценного "независимого" приложения на определённый путь, которое затем обрабатывает все подпути.
Это отличается от использования `APIRouter`, так как примонтированное приложение является полностью независимым.
OpenAPI и документация из вашего главного приложения не будут содержать ничего из примонтированного приложения, и т.д.
Это отличается от использования `APIRouter`, так как примонтированное приложение является полностью независимым. OpenAPI и документация из вашего главного приложения не будут содержать ничего из примонтированного приложения, и т.д.
Вы можете прочитать больше об этом в [Расширенном руководстве пользователя](../advanced/index.md).
+2 -2
View File
@@ -2,7 +2,7 @@
У вас может быть последовательность данных, которую вы хотите отправлять в «**потоке**». Это можно сделать с помощью **JSON Lines**.
/// info | Информация
/// note | Примечание
Добавлено в FastAPI 0.134.0.
@@ -48,7 +48,7 @@ sequenceDiagram
Это очень похоже на JSON-массив (эквивалент списка Python), но вместо того чтобы быть обернутым в `[]` и иметь `,` между элементами, здесь **один JSON-объект на строку**, они разделены символом новой строки.
/// info | Информация
/// note | Примечание
Важный момент в том, что ваше приложение сможет по очереди производить каждую строку, пока клиент потребляет предыдущие строки.
+8 -8
View File
@@ -8,7 +8,7 @@
## Использование класса `TestClient` { #using-testclient }
/// info | Информация
/// note | Примечание
Для использования класса `TestClient` сначала установите [`httpx`](https://www.python-httpx.org).
@@ -90,7 +90,7 @@ $ pip install httpx
│   └── test_main.py
```
Так как оба файла находятся в одной директории, для импорта объекта приложения из файла `main` в файл `test_main` Вы можете использовать относительный импорт:
Так как этот файл находится в том же пакете, для импорта объекта `app` из модуля `main` (`main.py`) Вы можете использовать относительный импорт:
{* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *}
@@ -113,7 +113,7 @@ $ pip install httpx
│   └── test_main.py
```
Предположим, что в файле `main.py` с приложением **FastAPI** есть несколько **операций пути**.
Предположим, что теперь в файле `main.py` с приложением **FastAPI** есть несколько других **операций пути**.
В нём описана операция `GET`, которая может вернуть ошибку.
@@ -125,26 +125,26 @@ $ pip install httpx
### Расширенный файл тестов { #extended-testing-file }
Теперь обновим файл `test_main.py`, добавив в него тестов:
Теперь можно обновить файл `test_main.py`, добавив в него расширенные тесты:
{* ../../docs_src/app_testing/app_b_an_py310/test_main.py *}
Если Вы не знаете, как передать информацию в запросе, можете воспользоваться поисковиком (погуглить) и задать вопрос: "Как передать информацию в запросе с помощью `httpx`", можно даже спросить: "Как передать информацию в запросе с помощью `requests`", поскольку дизайн HTTPX основан на дизайне Requests.
Если Вы не знаете, как передать информацию в запросе, можете воспользоваться поиском (Google) и задать вопрос: "Как передать информацию в запросе с помощью `httpx`", можно даже спросить: "Как передать информацию в запросе с помощью `requests`", поскольку дизайн HTTPX основан на дизайне Requests.
Затем Вы просто применяете найденные ответы в тестах.
Например:
* Передаёте *path*-параметры или *query*-параметры, вписав их непосредственно в строку URL.
* Чтобы передать *path*-параметр или *query*-параметр, добавьте его непосредственно в URL.
* Передаёте JSON в теле запроса, передав Python-объект (например: `dict`) через именованный параметр `json`.
* Если же Вам необходимо отправить *форму с данными* вместо JSON, то используйте параметр `data` вместо `json`.
* Если же Вам необходимо отправить *данные формы* вместо JSON, то используйте параметр `data` вместо `json`.
* Для передачи *HTTP-заголовков*, передайте объект `dict` через параметр `headers`.
* Для передачи *cookies* также передайте `dict`, но через параметр `cookies`.
Для получения дополнительной информации о передаче данных на бэкенд с помощью `httpx` или `TestClient` ознакомьтесь с [документацией HTTPX](https://www.python-httpx.org).
/// info | Информация
/// note | Примечание
Обратите внимание, что `TestClient` принимает данные, которые можно конвертировать в JSON, но не модели Pydantic.
+1 -1
View File
@@ -811,7 +811,7 @@ $ cd ~/code/prisoner-of-azkaban
$ python main.py
// Error importing sirius, it's not installed 😱
// Ошибка при импорте sirius, он не установлен 😱
Traceback (most recent call last):
File "main.py", line 1, in <module>
import sirius
+5 -5
View File
@@ -21,7 +21,7 @@ For the following technical terms, use these specific translations to ensure con
* path operation: операция пути (optionally clarify as `обработчик пути`)
* path operation function: функция-обработчик пути (or `функция обработки пути`)
* proprietary: проприетарный
* benchmark: бенчмарк (add (`тест производительности`) if clarification is needed or use just `тест производительности`)
* benchmark: бенчмарк (add `(тест производительности)` if clarification is needed or use just `тест производительности`)
* ASGI server: ASGI-сервер
* In a hurry? : Нет времени?
* response status code: статус-код ответа
@@ -42,7 +42,7 @@ For the following technical terms, use these specific translations to ensure con
* include: включать (add `в себя` if it's appropriate, or use `содержать` as an alternative)
* virtual environment: виртуальное окружение
* framework: фреймворк
* path paremeter: path-параметр
* path parameter: path-параметр
* path (as in URL path): путь
* form (as in HTML form): форма
* media type: тип содержимого (or `медиа-тип`)
@@ -76,9 +76,9 @@ For the following technical terms, use these specific translations to ensure con
* have the next best performance, after: быть на следующем месте по производительности после
* timing attack: тайминговая атака (clarify `атака по времени` if needed)
* OAuth2 scope: OAuth2 scope (clarify `область` if needed)
* TLS Termination Proxy: прокси-сервер TSL-терминации
* TLS Termination Proxy: прокси-сервер TLS-терминации
* utilize (resources): использовать
* сontent: содержимое (or `контент`)
* content: содержимое (or `контент`)
* raise exception: вызвать исключение (also possible to use `сгенерировать исключение` or `выбросить исключение`)
* password flow: password flow (clarify as `аутентификация по паролю` if needed)
* tutorial: руководство (or `учебник`)
@@ -95,7 +95,7 @@ For the following technical terms, use these specific translations to ensure con
* submodule: подмодуль
* subpackage: подпакет
* router: роутер
* building, deploying, accessing (when describing features of FastAPI Cloud): созданиe образа, развертывание и доступ
* building, deploying, accessing (when describing features of FastAPI Cloud): создание образа, развертывание и доступ
* type checker tool: инструмент проверки типов
Do not add whitespace in `т.д.`, `т.п.`.