diff --git a/docs/ru/docs/advanced/additional-responses.md b/docs/ru/docs/advanced/additional-responses.md index e671faa56..9a61beacf 100644 --- a/docs/ru/docs/advanced/additional-responses.md +++ b/docs/ru/docs/advanced/additional-responses.md @@ -2,33 +2,33 @@ /// warning | Предупреждение -Это довольно сложная тема. +Это достаточно сложная тема. -Если вы только начинаете с **FastAPI**, вам это может не понадобиться. +Если вы только начинаете работать с **FastAPI**, вам это может не понадобиться. /// -Вы можете объявить дополнительные ответы с дополнительными статус-кодами, медиа-типами, описаниями и т.д. +Вы можете объявлять дополнительные ответы с дополнительными статус-кодами, типами содержимого, описаниями и т.д. -Эти дополнительные ответы будут включены в OpenAPI схему, и они также будут отображаться в документации API. +Эти дополнительные ответы будут включены в схему OpenAPI, так что они также появятся в документации API. -Но для этих дополнительных ответов вы должны убедиться, что возвращаете `Response`, например `JSONResponse`, напрямую с вашим статус-кодом и содержимым. +Но для этих дополнительных ответов вы должны убедиться, что возвращаете `Response`, например, `JSONResponse` напрямую, с вашим статус-кодом и содержимым. ## Дополнительный ответ с `model` -Вы можете передать вашим *декораторам операций пути* параметр `responses`. +Вы можете передать своим декораторам *операций пути* параметр `responses`. -Он принимает `dict`: ключи - это статус-коды для каждого ответа (такие как `200`), а значения - другие `dict` с информацией для каждого из них. +Он принимает `dict`: ключами являются статус-коды для каждого ответа (например, `200`), а значениями являются другие `dict` с информацией для каждого из них. -Каждый из этих `dict` ответов может иметь ключ `model`, содержащий Pydantic модель, так же как и `response_model`. +Каждый из этих `dict` ответа может содержать ключ `model`, содержащий Pydantic-модель, как и `response_model`. **FastAPI** возьмет эту модель, сгенерирует ее JSON Schema и включит в нужное место в OpenAPI. -Например, чтобы объявить другой ответ с кодом состояния `404` и Pydantic моделью `Message`, можно написать: +Например, чтобы объявить другой ответ с кодом состояния `404` и Pydantic-моделью `Message`, вы можете написать: {* ../../docs_src/additional_responses/tutorial001.py hl[18,22] *} -/// note | Примечание +/// note | Заметка Имейте в виду, что вы должны вернуть `JSONResponse` напрямую. @@ -38,14 +38,14 @@ Ключ `model` не является частью OpenAPI. -**FastAPI** возьмет Pydantic модель оттуда, сгенерирует JSON Schema и разместит ее в нужном месте. +**FastAPI** возьмет Pydantic-модель оттуда, сгенерирует JSON Schema и поместит в нужное место. Правильное место: -* В ключе `content`, который имеет значение другого JSON объекта (`dict`), содержащего: - * Ключ с медиа-типом, например, `application/json`, который содержит как значение другой JSON объект, который содержит: - * Ключ `schema`, который имеет как значение JSON Schema из модели, вот это правильное место. - * **FastAPI** добавляет ссылку здесь на глобальные JSON Schema в другом месте вашего OpenAPI вместо того, чтобы включать её напрямую. Таким образом, другие приложения и клиенты могут использовать эти JSON Schema напрямую, предоставлять лучшие инструменты для генерации кода и т.д. +* В ключе `content`, который имеет значение другой JSON объект (`dict`), содержащий: + * Ключ с типом содержимого, например `application/json`, который в качестве значения содержит другой JSON объект, содержащий: + * Ключ `schema`, который имеет в качестве значения JSON Schema из модели, вот куда нужно поместить. + * **FastAPI** добавляет сюда ссылку на глобальные JSON Schemas в другом месте вашего OpenAPI вместо того, чтобы включать его напрямую. Таким образом, другие приложения и клиенты могут использовать эти JSON Schemas напрямую, предоставлять лучшие инструменты генерации кода и другие функции. /// @@ -55,7 +55,7 @@ { "responses": { "404": { - "description": "Additional Response", + "description": "Дополнительный ответ", "content": { "application/json": { "schema": { @@ -65,7 +65,7 @@ } }, "200": { - "description": "Successful Response", + "description": "Успешный ответ", "content": { "application/json": { "schema": { @@ -75,7 +75,7 @@ } }, "422": { - "description": "Validation Error", + "description": "Ошибка валидации", "content": { "application/json": { "schema": { @@ -88,75 +88,75 @@ } ``` -Схемы ссылаются на другое место внутри OpenAPI схемы: +Схемы ссылаются на другое место внутри схемы OpenAPI: ```JSON hl_lines="4-16" { "components": { "schemas": { "Message": { - "title": "Message", + "title": "Сообщение", "required": [ - "message" + "сообщение" ], "type": "object", "properties": { - "message": { - "title": "Message", + "сообщение": { + "title": "Сообщение", "type": "string" } } }, "Item": { - "title": "Item", + "title": "Предмет", "required": [ - "id", - "value" + "идентификатор", + "значение" ], "type": "object", "properties": { - "id": { - "title": "Id", + "идентификатор": { + "title": "Идентификатор", "type": "string" }, - "value": { - "title": "Value", + "значение": { + "title": "Значение", "type": "string" } } }, "ValidationError": { - "title": "ValidationError", + "title": "Ошибка валидации", "required": [ - "loc", - "msg", - "type" + "местоположение", + "сообщение", + "тип" ], "type": "object", "properties": { - "loc": { + "местоположение": { "title": "Location", "type": "array", "items": { "type": "string" } }, - "msg": { - "title": "Message", + "сообщение": { + "title": "Сообщение", "type": "string" }, - "type": { - "title": "Error Type", + "тип": { + "title": "Тип ошибки", "type": "string" } } }, "HTTPValidationError": { - "title": "HTTPValidationError", + "title": "Ошибка валидации HTTP", "type": "object", "properties": { - "detail": { - "title": "Detail", + "детали": { + "title": "Детали", "type": "array", "items": { "$ref": "#/components/schemas/ValidationError" @@ -169,51 +169,51 @@ } ``` -## Дополнительные медиа-типы для основного ответа +## Дополнительные типы содержимого для основного ответа -Вы можете использовать тот же параметр `responses` для добавления различных медиа-типов для одного и того же основного ответа. +Вы можете использовать этот же параметр `responses`, чтобы добавить разные типы содержимого для одного и того же основного ответа. -Например, можно добавить дополнительный медиа-тип `image/png`, объявляя, что ваша *операция пути* может возвращать JSON объект (с медиа-типом `application/json`) или PNG изображение: +Например, вы можете добавить дополнительный медиа-тип `image/png`, объявив, что ваши *операции пути* могут возвращать JSON объект (с медиа-типом `application/json`) или изображение PNG: {* ../../docs_src/additional_responses/tutorial002.py hl[19:24,28] *} -/// note | Примечание +/// note | Заметка -Обратите внимание, что вы должны вернуть изображение, используя `FileResponse` напрямую. +Обратите внимание, что вы должны возвращать изображение, используя `FileResponse` напрямую. /// /// info | Информация -Если вы не укажете явный медиа-тип в вашем `responses` параметре, FastAPI будет предполагать, что ответ имеет тот же медиа-тип, что и основной класс ответа (по умолчанию `application/json`). +Если вы явно не указываете другой тип содержимого в вашем параметре `responses`, FastAPI предположит, что ответ имеет тот же тип содержимого, что и основной класс ответа (по умолчанию `application/json`). -Но если вы указали пользовательский класс ответа с `None` в качестве его медиа-типа, FastAPI будет использовать `application/json` для любого дополнительного ответа, который связан с моделью. +Но если вы задали пользовательский класс ответа с `None` в качестве типа содержимого, FastAPI будет использовать `application/json` для любого дополнительного ответа, у которого есть ассоциированная модель. /// ## Комбинирование информации -Вы также можете объединять информацию об ответах из нескольких мест, включая параметры `response_model`, `status_code` и `responses`. +Вы также можете комбинировать информацию о ответах из разных мест, включая параметры `response_model`, `status_code` и `responses`. -Вы можете объявить `response_model`, используя статус-код по умолчанию `200` (или пользовательский, если вам нужно), а затем объявить дополнительную информацию для этого же ответа в `responses`, напрямую в OpenAPI схеме. +Вы можете объявить `response_model`, используя стандартный статус-код `200` (или пользовательский, если необходимо), а затем объявить дополнительную информацию для этого же ответа в `responses`, напрямую в схеме OpenAPI. -**FastAPI** сохранит дополнительную информацию из `responses` и объединит её с JSON Schema вашей модели. +**FastAPI** сохранит дополнительную информацию из `responses` и объединит ее с JSON Schema из вашей модели. -Например, вы можете объявить ответ с кодом состояния `404`, который использует Pydantic модель и имеет пользовательское `description`. +Например, вы можете объявить ответ с кодом состояния `404`, который использует Pydantic-модель и имеет пользовательское `description`. И ответ с кодом состояния `200`, который использует ваш `response_model`, но включает пользовательский `example`: {* ../../docs_src/additional_responses/tutorial003.py hl[20:31] *} -Все это будет объединено и включено в ваш OpenAPI и показано в документации API: +Все это будет объединено и включено в ваш OpenAPI, и показано в документации API: -## Комбинирование предопределенных ответов и пользовательских +## Комбинирование предопределенных и пользовательских ответов -Возможно, вы захотите иметь некоторые предопределенные ответы, которые применяются к многим *операциям пути*, но вы хотите объединить их с пользовательскими ответами, необходимыми для каждой *операции пути*. +Возможно, вы захотите иметь некоторые предопределенные ответы, которые применяются ко многим *операциям пути*, но хотите объединить их с пользовательскими ответами, необходимыми для каждой *операции пути*. -В таких случаях вы можете использовать технику Python "распаковки" `dict` с помощью `**dict_to_unpack`: +Для таких случаев вы можете использовать технику Python "распаковка" `dict` с помощью `**dict_to_unpack`: ```Python old_dict = { @@ -223,7 +223,7 @@ old_dict = { new_dict = {**old_dict, "new key": "new value"} ``` -Здесь, `new_dict` будет содержать все пары ключ-значение из `old_dict` плюс новую пару ключ-значение: +Здесь, `new_dict` будет содержать все пары `ключ-значение` из `old_dict` плюс новую пару `ключ-значение`: ```Python { @@ -233,15 +233,15 @@ new_dict = {**old_dict, "new key": "new value"} } ``` -Вы можете использовать эту технику для повторного использования некоторых предопределенных ответов в ваших *операциях пути* и сочетания их с дополнительными пользовательскими ответами. +Вы можете использовать эту технику для повторного использования некоторых предопределенных ответов в ваших *операциях пути* и объединить их с дополнительными пользовательскими. Например: {* ../../docs_src/additional_responses/tutorial004.py hl[13:17,26] *} -## Дополнительная информация об OpenAPI ответах +## Больше информации об ответах OpenAPI -Чтобы узнать, что именно можно включить в ответы, вы можете проверить эти разделы в спецификации OpenAPI: +Чтобы узнать, что именно можно включить в ответы, вы можете посмотреть эти разделы в спецификации OpenAPI: * OpenAPI Responses Object, включает в себя `Response Object`. -* OpenAPI Response Object, вы можете включить что угодно из этого напрямую для каждого ответа в вашем параметре `responses`. Включая `description`, `headers`, `content` (внутри этого вы объявляете различные медиа-типы и JSON schemas), и `links`. +* OpenAPI Response Object, вы можете включить что угодно из этого напрямую в каждый ответ внутри вашего параметра `responses`. Включая `description`, `headers`, `content` (внутри этого вы указываете разные типы медиа и JSON Schemas), и `links`. diff --git a/docs/ru/docs/advanced/advanced-dependencies.md b/docs/ru/docs/advanced/advanced-dependencies.md index f676b3e6c..2a44a479e 100644 --- a/docs/ru/docs/advanced/advanced-dependencies.md +++ b/docs/ru/docs/advanced/advanced-dependencies.md @@ -1,34 +1,34 @@ # Продвинутые зависимости -## Параметризованные зависимости +## Параметризуемые зависимости -Все зависимости, которые мы видели ранее, это фиксированные функции или классы. +Все зависимости, которые мы видели, являются фиксированной функцией или классом. -Но могут возникать случаи, когда вам нужно задать параметры зависимости, не объявляя множество разных функций или классов. +Но могут быть случаи, когда вы захотите иметь возможность задавать параметры для зависимости, не объявляя множество разных функций или классов. -Представим, что мы хотим иметь зависимость, которая проверяет, содержит ли параметр запроса `q` определенное фиксированное содержимое. +Представим, что мы хотим иметь зависимость, которая проверяет, содержит ли параметр запроса `q` некоторое фиксированное содержимое. -Но мы хотим иметь возможность параметризовать это фиксированное содержимое. +Но нам нужно иметь возможность параметризовать это фиксированное содержимое. -## Экземпляр "callable" +## "Вызываемый" экземпляр -В Python есть способ сделать экземпляр класса "вызваемым" (callable). +В Python есть способ сделать экземпляр класса "вызываемым". -Не сам класс (который уже является вызваемым), а именно экземпляр этого класса. +Не сам класс (он уже может быть вызываемым), а экземпляр этого класса. Для этого мы объявляем метод `__call__`: {* ../../docs_src/dependencies/tutorial011_an_py39.py hl[12] *} -В этом случае этот `__call__` используется **FastAPI** для проверки дополнительных параметров и подзависимости, и это то, что будет вызвано для передачи значения в параметр в вашей функции *операции пути* позже. +В этом случае **FastAPI** будет использовать этот `__call__` для проверки дополнительных параметров и под-зависимостей, и он будет вызываться для передачи значения в параметр вашей *функции-обработчика пути* позже. ## Параметризация экземпляра -Теперь мы можем использовать `__init__` для объявления параметров экземпляра, которые мы можем использовать для "параметризации" зависимости: +Теперь мы можем использовать `__init__`, чтобы объявить параметры экземпляра, которые мы можем использовать для "параметризации" зависимости: {* ../../docs_src/dependencies/tutorial011_an_py39.py hl[9] *} -В этом случае **FastAPI** никогда не дотронется до или не будет интересоваться `__init__`, мы будем использовать его напрямую в нашем коде. +В данном случае **FastAPI** никогда не будет касаться или заботиться об `__init__`, мы будем использовать его напрямую в нашем коде. ## Создание экземпляра @@ -36,30 +36,30 @@ {* ../../docs_src/dependencies/tutorial011_an_py39.py hl[18] *} -Таким образом, мы можем "параметризовать" нашу зависимость, которая теперь содержит `"bar"`, как атрибут `checker.fixed_content`. +Таким образом, мы можем "параметризовать" нашу зависимость, в которой теперь есть `"bar"`, как атрибут `checker.fixed_content`. ## Использование экземпляра в качестве зависимости -Затем мы можем использовать этот `checker` в `Depends(checker)`, вместо `Depends(FixedContentQueryChecker)`, потому что зависимость — это экземпляр `checker`, а не сам класс. +Затем мы могли бы использовать этот `checker` в `Depends(checker)`, вместо `Depends(FixedContentQueryChecker)`, потому что зависимость — это экземпляр `checker`, а не сам класс. -И при разрешении зависимости **FastAPI** вызовет этот `checker` следующим образом: +И при разрешении зависимости, **FastAPI** вызовет этот `checker` так: ```Python checker(q="somequery") ``` -...и передаст то, что это возвращает, как значение зависимости в нашей функции *операции пути* как параметр `fixed_content_included`: +...и передаст то, что это возвращает, как значение зависимости в нашей *функции-обработчике пути* как параметр `fixed_content_included`: {* ../../docs_src/dependencies/tutorial011_an_py39.py hl[22] *} /// tip | Совет -Все это может показаться надуманным. И может быть не совсем ясно, насколько это полезно. +Все это может показаться надуманным. И пока не совсем ясно, насколько это полезно. Эти примеры намеренно просты, но показывают, как все работает. -В разделах о безопасности есть вспомогательные функции, которые реализованы точно таким же образом. +В главах о безопасности есть утилиты-функции, которые реализованы таким же образом. -Если вы поняли все это, вы уже знаете, как эти инструменты безопасности работают под капотом. +Если вы все это поняли, вы уже знаете, как работают эти утилиты для безопасности изнутри. /// diff --git a/docs/ru/docs/advanced/behind-a-proxy.md b/docs/ru/docs/advanced/behind-a-proxy.md index c3497d18c..0d4b60c07 100644 --- a/docs/ru/docs/advanced/behind-a-proxy.md +++ b/docs/ru/docs/advanced/behind-a-proxy.md @@ -1,34 +1,34 @@ -# За прокси +# За прокси-сервером -В некоторых случаях вам может понадобиться воспользоваться сервером **прокси**, таким как Traefik или Nginx, с конфигурацией, которая добавляет дополнительный префикс пути, не видимый вашему приложению. +В некоторых ситуациях вам может понадобиться использовать **прокси**-сервер, такой как Traefik или Nginx, с конфигурацией, добавляющей дополнительный префикс к path, который ваше приложение не видит. В таких случаях вы можете использовать `root_path` для настройки вашего приложения. -`root_path` — это механизм, предусмотренный спецификацией ASGI (на которой построен FastAPI через Starlette). +`root_path` — это механизм, предоставляемый спецификацией ASGI (на основе которой построен FastAPI через Starlette). -`root_path` используется для обработки этих специфических случаев. +`root_path` используется для обработки этих конкретных случаев. -Также он используется внутренне при монтировании подприложений. +Он также используется внутренне при монтировании подприложений. -## Прокси с обрезанным префиксом пути +## Прокси с вырезанным префиксом path -Наличие прокси с обрезанным префиксом пути в этом случае означает, что вы можете объявить путь `/app` в вашем коде, но затем добавить слой сверху (прокси), который поместит ваше приложение **FastAPI** под путь вроде `/api/v1`. +Использование прокси с вырезанным префиксом path означает, что вы можете объявить путь как `/app` в своем коде. Но затем вы добавляете слой сверху (прокси), который помещает ваше приложение **FastAPI** под путь, такой как `/api/v1`. -В этом случае изначальный путь `/app` на самом деле будет обслуживаться по адресу `/api/v1/app`. +В этом случае оригинальный путь `/app` будет фактически работать как `/api/v1/app`. -Хотя весь ваш код написан, предполагая, что существует только `/app`. +Несмотря на то, что весь ваш код написан с учетом использования только `/app`. {* ../../docs_src/behind_a_proxy/tutorial001.py hl[6] *} -И прокси будет **"обрезать"** **префикс пути** на лету перед передачей запроса на сервер приложения (вероятно, через FastAPI CLI через Uvicorn), оставляя ваше приложение уверенным в том, что оно обслуживается по адресу `/app`, чтобы вам не нужно было обновлять весь ваш код для включения префикса `/api/v1`. +И прокси будет **"вырезать"** **префикс пути** на лету перед передачей запроса серверу приложения (вероятно, Uvicorn через CLI FastAPI), оставляя ваше приложение уверенным, что оно работает на `/app`, чтобы вам не пришлось обновлять весь код для включения префикса `/api/v1`. До этого момента все будет работать как обычно. -Но затем, когда вы откроете интегрированный интерфейс документации (фронтенд), он будет ожидать, что получит схему OpenAPI по адресу `/openapi.json`, вместо `/api/v1/openapi.json`. +Но затем, когда вы откроете встроенный интерфейс документации (фронтенд), он будет ожидать получить OpenAPI-схему на `/openapi.json`, вместо `/api/v1/openapi.json`. -Таким образом, фронтенд (который выполняется в браузере) попытается получить доступ к `/openapi.json` и не сможет получить схему OpenAPI. +Поэтому фронтенд (который работает в браузере) попытается достичь `/openapi.json` и не сможет получить OpenAPI-схему. -Поскольку у нас есть прокси с префиксом пути `/api/v1` для нашего приложения, фронтенд должен получить схему OpenAPI по адресу `/api/v1/openapi.json`. +Поскольку у нас есть прокси с префиксом пути `/api/v1` для нашего приложения, фронтенд должен получить OpenAPI-схему на `/api/v1/openapi.json`. ```mermaid graph LR @@ -41,13 +41,13 @@ browser --> proxy proxy --> server ``` -/// tip | Совет +/// совет | Совет IP `0.0.0.0` обычно используется, чтобы указать, что программа слушает все доступные IP-адреса на этой машине/сервере. /// -UI документации также будет нужна схема OpenAPI, чтобы указать, что этот API `server` находится по адресу `/api/v1` (за прокси). Например: +Интерфейс документации также будет нуждаться в OpenAPI-схеме для декларации, что этот API `server` расположен на `/api/v1` (за прокси). Например: ```JSON hl_lines="4-8" { @@ -64,37 +64,37 @@ UI документации также будет нужна схема OpenAPI, } ``` -В этом примере "Прокси" может быть чем-то вроде **Traefik**. А сервер будет чем-то вроде FastAPI CLI с **Uvicorn**, выполняющим ваше приложение FastAPI. +В этом примере "Прокси" может быть чем-то вроде **Traefik**. А сервером может быть что-то вроде CLI FastAPI с **Uvicorn**, который запускает ваше приложение FastAPI. -### Предоставление `root_path` +### Указание `root_path` -Для этого вы можете использовать параметр командной строки `--root-path`, например: +Чтобы достичь этого, вы можете использовать командную строку с опцией `--root-path`, например:
```console $ fastapi run main.py --root-path /api/v1 -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +INFO: Uvicorn запущен на http://127.0.0.1:8000 (Нажмите CTRL+C для остановки) ```
Если вы используете Hypercorn, у него также есть опция `--root-path`. -/// note | Технические детали +/// note | Технические подробности Спецификация ASGI определяет `root_path` для этого случая использования. -А параметр командной строки `--root-path` предоставляет этот `root_path`. +И опция командной строки `--root-path` предоставляет этот `root_path`. /// ### Проверка текущего `root_path` -Вы можете получить текущий `root_path`, используемый вашим приложением для каждого запроса, он является частью словаря `scope` (который является частью спецификации ASGI). +Вы можете получить текущий `root_path`, используемый вашим приложением для каждого запроса, он является частью словаря `scope` (это часть спецификации ASGI). -Здесь мы приводим его в сообщении только для демонстрационных целей. +Здесь мы включаем его в сообщение просто для демонстрации. {* ../../docs_src/behind_a_proxy/tutorial001.py hl[8] *} @@ -105,60 +105,60 @@ $ fastapi run main.py --root-path /api/v1 ```console $ fastapi run main.py --root-path /api/v1 -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +INFO: Uvicorn запущен на http://127.0.0.1:8000 (Нажмите CTRL+C для остановки) ``` -Ответ будет таким: +Ответ будет что-то вроде: ```JSON { - "message": "Здравствуй, мир", + "message": "Hello World", "root_path": "/api/v1" } ``` ### Установка `root_path` в приложении FastAPI -В качестве альтернативы, если у вас нет возможности предоставить параметр командной строки, такой как `--root-path` или эквивалентный, вы можете установить параметр `root_path` при создании вашего приложения FastAPI: +Альтернативно, если у вас нет возможности предоставить опцию командной строки, такую как `--root-path` или аналогичную, вы можете установить параметр `root_path` при создании вашего приложения FastAPI: {* ../../docs_src/behind_a_proxy/tutorial002.py hl[3] *} -Передача `root_path` в `FastAPI` будет эквивалентна передаче параметра командной строки `--root-path` в Uvicorn или Hypercorn. +Передача `root_path` в `FastAPI` будет эквивалентна передаче опции командной строки `--root-path` для Uvicorn или Hypercorn. ### О `root_path` -Учтите, что сервер (Uvicorn) не будет использовать этот `root_path` для чего-либо, кроме передачи его в приложение. +Учтите, что сервер (Uvicorn) не будет использовать `root_path` ни для чего, кроме передачи его приложению. -Но если вы пойдете с вашим браузером на http://127.0.0.1:8000/app, вы увидите нормальный ответ: +Но если вы зайдете через браузер по адресу http://127.0.0.1:8000/app, вы увидите обычный ответ: ```JSON { - "message": "Здравствуй, мир", + "message": "Hello World", "root_path": "/api/v1" } ``` -Таким образом, он не будет ожидать доступа по адресу `http://127.0.0.1:8000/api/v1/app`. +Итак, он не будет ожидать доступа по адресу `http://127.0.0.1:8000/api/v1/app`. -Uvicorn будет ожидать, что прокси будет обращаться к Uvicorn по адресу `http://127.0.0.1:8000/app`, и тогда это будет обязанностью прокси добавить дополнительный префикс `/api/v1` поверх. +Uvicorn будет ожидать, что прокси получит доступ к Uvicorn по адресу `http://127.0.0.1:8000/app`, а затем это будет уже ответственность прокси — добавить дополнительный префикс `/api/v1`. -## О прокси с обрезанным префиксом пути +## О прокси с вырезанным префиксом path -Учтите, что использование прокси с обрезанным префиксом пути — это только один из способов его настройки. +Имейте в виду, что прокси с вырезанным префиксом path — это всего лишь один из способов его настройки. -Вероятно, в большинстве случаев по умолчанию прокси не будет иметь обрезанного префикса пути. +Вероятно, во многих случаях по умолчанию будет то, что у прокси нет вырезанного префикса path. -В таком случае (без обрезанного префикса пути) прокси будет слушать что-то вроде `https://myawesomeapp.com`, и тогда, если браузер зайдет на `https://myawesomeapp.com/api/v1/app`, а ваш сервер (например, Uvicorn) слушает на `http://127.0.0.1:8000`, прокси (без обрезанного префикса пути) будет обращаться к Uvicorn по тому же пути: `http://127.0.0.1:8000/api/v1/app`. +В случае, подобном этому (без вырезанного префикса path), прокси будет слушать что-то вроде `https://myawesomeapp.com`, и тогда, если браузер перейдет на `https://myawesomeapp.com/api/v1/app`, а ваш сервер (например, Uvicorn) слушает на `http://127.0.0.1:8000`, прокси (без вырезанного префикса path) получит доступ к Uvicorn на том же пути: `http://127.0.0.1:8000/api/v1/app`. ## Тестирование локально с Traefik -Вы можете легко запустить эксперимент локально с обрезанным префиксом пути, используя Traefik. +Вы можете легко провести эксперимент локально с вырезанным префиксом path, используя Traefik. -Скачайте Traefik, это единый исполняемый файл, вы можете извлечь сжатый файл и запустить его напрямую из терминала. +Скачайте Traefik, это один исполняемый файл, вы можете извлечь сжатый файл и запустить его прямо из терминала. -Затем создайте файл `traefik.toml` со следующим содержимым: +Затем создайте файл `traefik.toml` с: ```TOML hl_lines="3" [entryPoints] @@ -172,9 +172,9 @@ Uvicorn будет ожидать, что прокси будет обращат Это указывает Traefik слушать на порту 9999 и использовать другой файл `routes.toml`. -/// tip | Совет +/// совет -Мы используем порт 9999 вместо стандартного HTTP-порта 80, чтобы вам не нужно было запускать его с административными (`sudo`) привилегиями. +Мы используем порт 9999 вместо стандартного порта HTTP 80, чтобы вам не пришлось запускать это с привилегиями администратора (`sudo`). /// @@ -203,9 +203,9 @@ Uvicorn будет ожидать, что прокси будет обращат url = "http://127.0.0.1:8000" ``` -Этот файл настраивает Traefik на использование префикса пути `/api/v1`. +Этот файл настраивает Traefik для использования префикса path `/api/v1`. -И затем Traefik будет перенаправлять свои запросы на ваш Uvicorn, работающий на `http://127.0.0.1:8000`. +А затем Traefik перенаправит свои запросы на ваш Uvicorn, запущенный на `http://127.0.0.1:8000`. Теперь запустите Traefik: @@ -214,98 +214,98 @@ Uvicorn будет ожидать, что прокси будет обращат ```console $ ./traefik --configFile=traefik.toml -INFO[0000] Configuration loaded from file: /home/user/awesomeapi/traefik.toml +INFO[0000] Конфигурация загружена из файла: /home/user/awesomeapi/traefik.toml ``` -И теперь запустите ваше приложение, используя параметр `--root-path`: +И теперь запустите ваше приложение, используя опцию `--root-path`:
```console $ fastapi run main.py --root-path /api/v1 -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +INFO: Uvicorn запущен на http://127.0.0.1:8000 (Нажмите CTRL+C для остановки) ```
-### Проверка ответов +### Проверьте ответы -Теперь, если вы перейдете по URL-адресу с портом для Uvicorn: http://127.0.0.1:8000/app, вы увидите стандартный ответ: +Теперь, если вы перейдете по URL с портом для Uvicorn: http://127.0.0.1:8000/app, вы увидите нормальный ответ: ```JSON { - "message": "Здравствуй, мир", + "message": "Hello World", "root_path": "/api/v1" } ``` -/// tip | Совет +/// совет | Совет -Заметьте, что, хотя вы обращаетесь к нему по адресу `http://127.0.0.1:8000/app`, он показывает `root_path` как `/api/v1`, взятый из параметра `--root-path`. +Обратите внимание, что, хотя вы получаете доступ к нему по адресу `http://127.0.0.1:8000/app`, он отображает `root_path` как `/api/v1`, взятый из опции `--root-path`. /// -А теперь откройте URL с портом для Traefik, включая префикс пути: http://127.0.0.1:9999/api/v1/app. +А теперь откройте URL с портом для Traefik, включая префикс path: http://127.0.0.1:9999/api/v1/app. Мы получаем такой же ответ: ```JSON { - "message": "Здравствуй, мир", + "message": "Hello World", "root_path": "/api/v1" } ``` -только на этот раз по адресу URL с префиксом, предоставленным прокси: `/api/v1`. +но на этот раз по URL с префиксом path, предоставленным прокси: `/api/v1`. -Конечно, идея в том, чтобы все получали доступ к приложению через прокси, поэтому версия с префиксом пути `/api/v1` является "правильной". +Конечно, идея здесь в том, что все должны получить доступ к приложению через прокси, так что версия с префиксом path `/api/v1` — это "правильная" версия. -А версия без префикса пути (`http://127.0.0.1:8000/app`), предоставленная напрямую Uvicorn, будет исключительно для доступа _прокси_ (Traefik) к нему. +И версия без префикса path (`http://127.0.0.1:8000/app`), предоставляемая напрямую Uvicorn, будет исключительно для _прокси_ (Traefik), чтобы получить к ней доступ. -Это демонстрирует, как прокси (Traefik) использует префикс пути и как сервер (Uvicorn) использует `root_path` из параметра `--root-path`. +Это демонстрирует, как прокси (Traefik) использует префикс path и как сервер (Uvicorn) использует `root_path` из опции `--root-path`. -### Проверка UI документации +### Проверьте интерфейс документации -Но вот интересная часть. ✨ +Но вот где начинается веселье. ✨ -"Официальный" способ доступа к приложению будет через прокси с префиксом пути, который мы определили. Таким образом, как мы и ожидали, если вы попытаетесь использовать UI документации, предоставляемый напрямую Uvicorn, без префикса пути в URL, это не будет работать, так как он ожидает, что доступ будет через прокси. +"Официальный" способ доступа к приложению будет через прокси с префиксом path, который мы определили. Поэтому, как и ожидалось, если вы попытаетесь использовать интерфейс документации, обслуживаемый Uvicorn напрямую, без префикса path в URL, он не будет работать, потому что предполагается, что доступ будет осуществляться через прокси. -Вы можете проверить это на http://127.0.0.1:8000/docs: +Вы можете проверить это по адресу http://127.0.0.1:8000/docs: -Но если мы получим доступ к UI документации по "официальному" URL с использованием прокси с портом `9999`, по `/api/v1/docs`, он работает правильно! 🎉 +Но если мы получим доступ к интерфейсу документации по "официальному" URL, используя прокси с портом `9999`, по адресу `/api/v1/docs`, он работает правильно! 🎉 -Можно проверить это на http://127.0.0.1:9999/api/v1/docs: +Вы можете проверить это по адресу http://127.0.0.1:9999/api/v1/docs: -Точно так, как мы и хотели. ✔️ +Как и хотели. ✔️ -Это потому, что FastAPI использует этот `root_path` для создания стандартного `server` в OpenAPI с URL, предоставленным `root_path`. +Это потому, что FastAPI использует этот `root_path` для создания `server` по умолчанию в OpenAPI с URL, предоставленным `root_path`. ## Дополнительные серверы /// warning | Предупреждение -Это более сложный случай использования. Смело пропускайте его. +Это более сложный случай использования. Вы можете пропустить его, если хотите. /// По умолчанию **FastAPI** создаст `server` в схеме OpenAPI с URL для `root_path`. -Но вы также можете предоставить другие альтернативные `servers`, например, если вы хотите, чтобы *тот же* UI документации взаимодействовал как с окружением для тестирования, так и с производственным окружением. +Но вы также можете предоставить другие альтернативные `servers`, например, если вы хотите, чтобы *этот же* интерфейс документации взаимодействовал как со средой тестирования, так и со средой продакшн. -Если вы передадите кастомный список `servers` и присутствует `root_path` (потому что ваш API находится за прокси), **FastAPI** вставит "server" с этим `root_path` в начало списка. +Если вы передаете пользовательский список `servers` и существует `root_path` (потому что ваш API находится за прокси), **FastAPI** вставит "server" с этим `root_path` в начало списка. Например: {* ../../docs_src/behind_a_proxy/tutorial003.py hl[4:7] *} -Сгенерирует схему OpenAPI, такую как: +Создаст схему OpenAPI, как: ```JSON hl_lines="5-7" { @@ -317,11 +317,11 @@ $ fastapi run main.py --root-path /api/v1 }, { "url": "https://stag.example.com", - "description": "Staging environment" + "description": "Тестовая среда" }, { "url": "https://prod.example.com", - "description": "Production environment" + "description": "Продакшн среда" } ], "paths": { @@ -330,23 +330,23 @@ $ fastapi run main.py --root-path /api/v1 } ``` -/// tip | Совет +/// совет | Совет -Обратите внимание на автоматически сгенерированный сервер с значением `url` `/api/v1`, взятое из `root_path`. +Обратите внимание на автоматически сгенерированный сервер с `url` значением `/api/v1`, взятым из `root_path`. /// -В UI документации по адресу http://127.0.0.1:9999/api/v1/docs это будет выглядеть так: +В интерфейсе документации по адресу http://127.0.0.1:9999/api/v1/docs это будет выглядеть так: -/// tip | Совет +/// совет | Совет -UI документации будет взаимодействовать с сервером, который вы выберете. +Интерфейс документации будет взаимодействовать с сервером, который вы выберете. /// -### Отключить автоматический сервер из `root_path` +### Отключение автоматического сервера от `root_path` Если вы не хотите, чтобы **FastAPI** включал автоматический сервер, используя `root_path`, вы можете использовать параметр `root_path_in_servers=False`: @@ -356,6 +356,6 @@ UI документации будет взаимодействовать с с ## Монтирование подприложения -Если вам нужно смонтировать подприложение (как описано в [Подприложения - Монтирование](sub-applications.md){.internal-link target=_blank}), при этом используя прокси с `root_path`, вы можете сделать это нормально, как вы и ожидаете. +Если вам нужно смонтировать подприложение (как описано в [Подприложения - Монтирование](sub-applications.md){.internal-link target=_blank}), используя также прокси с `root_path`, вы можете сделать это обычным образом, как и ожидалось. -FastAPI будет внутри использовать `root_path` умно, так что все будет просто работать. ✨ +FastAPI будет использовать `root_path` умно, поэтому все будет работать, как и задумано. ✨ diff --git a/docs/ru/docs/advanced/custom-response.md b/docs/ru/docs/advanced/custom-response.md index 74609c59c..182ec4909 100644 --- a/docs/ru/docs/advanced/custom-response.md +++ b/docs/ru/docs/advanced/custom-response.md @@ -1,42 +1,42 @@ # Пользовательский ответ - HTML, поток, файл и другие -По умолчанию, **FastAPI** будет возвращать ответы, используя `JSONResponse`. +По умолчанию **FastAPI** будет возвращать ответы, используя `JSONResponse`. -Вы можете переопределить это, возвращая `Response` напрямую, как показано в [Возврат ответа напрямую](response-directly.md){.internal-link target=_blank}. +Вы можете переопределить это, возвращая `Response` напрямую, как показано в разделе [Возврат Response напрямую](response-directly.md){.internal-link target=_blank}. -Но если вы возвращаете `Response` напрямую (или любой подкласс, например, `JSONResponse`), данные не будут автоматически преобразованы (даже если вы объявите `response_model`), и документация не будет автоматически сгенерирована (например, включая конкретный "media type", в HTTP заголовке `Content-Type` как часть сгенерированного OpenAPI). +Но если вы возвращаете `Response` напрямую (или любой подкласс, такой как `JSONResponse`), данные не будут автоматически конвертироваться (даже если вы объявите `response_model`), и документация не будет автоматически генерироваться (например, включая конкретный "тип содержимого", в HTTP-заголовке `Content-Type` как часть генерируемого OpenAPI). -Но вы также можете объявить `Response`, который вы хотите использовать (например, любой подкласс `Response`), в *декораторе операции пути* с использованием параметра `response_class`. +Но вы также можете объявить `Response`, который хотите использовать (например, любой подкласс `Response`), в *декораторе операции пути*, используя параметр `response_class`. -Содержание, которое вы возвращаете из вашей *функции операции пути*, будет помещено внутрь этого `Response`. +Содержимое, которое вы возвращаете из вашей *функции-обработчика пути*, будет помещено внутрь этого `Response`. -И если этот `Response` имеет тип носителя JSON (`application/json`), как в случае с `JSONResponse` и `UJSONResponse`, данные, которые вы возвращаете, будут автоматически преобразованы (и отфильтрованы) с любым Pydantic `response_model`, который вы объявили в *декораторе операции пути*. +И если этот `Response` имеет JSON тип содержимого (`application/json`), как в случае с `JSONResponse` и `UJSONResponse`, данные, которые вы возвращаете, будут автоматически конвертироваться (и фильтроваться) с помощью любого Pydantic `response_model`, который вы объявили в *декораторе операции пути*. -/// note | Заметка +/// note | Замечание -Если вы используете класс ответа без типа носителя, FastAPI ожидает, что ваш ответ будет без содержимого, поэтому формат ответа не будет задокументирован в сгенерированных OpenAPI документах. +Если вы используете класс ответа без типа содержимого, FastAPI ожидает, что ваш ответ не будет содержать контент, поэтому он не задокументирует формат ответа в автоматически генерируемой документации OpenAPI. /// -## Используйте `ORJSONResponse` +## Использование `ORJSONResponse` -Например, если вы хотите повысить производительность, вы можете установить и использовать `orjson` и установить ответ в `ORJSONResponse`. +Например, если вы заботитесь о производительности, вы можете установить и использовать `orjson` и установить ответ `ORJSONResponse`. -Импортируйте класс `Response` (подкласс), который вы хотите использовать, и объявите его в *декораторе операции пути*. +Импортируйте класс (подкласс) `Response`, который вы хотите использовать, и объявите его в *декораторе операции пути*. Для больших ответов возврат `Response` напрямую значительно быстрее, чем возврат словаря. -Это потому, что по умолчанию, FastAPI будет проверять каждый элемент внутри и удостоверяться, что он сериализуем в JSON, используя тот же [Совместимый с JSON кодировщик](../tutorial/encoder.md){.internal-link target=_blank}, описанный в тутореале. Это то, что позволяет вам возвращать **произвольные объекты**, например, модели базы данных. +Это происходит потому, что по умолчанию FastAPI будет проверять каждый элемент внутри и убеждаться, что он сериализуем как JSON, используя тот же [Совместимый с JSON кодировщик](../tutorial/encoder.md){.internal-link target=_blank}, о котором рассказано в руководстве. Это позволяет вам возвращать **произвольные объекты**, например, модели базы данных. -Но если вы уверены, что содержание, которое вы возвращаете, **сериализуемо в JSON**, вы можете передать его напрямую в класс ответов и избежать дополнительной нагрузки, которая возникла бы у FastAPI, пропуская ваше возвращаемое содержимое через `jsonable_encoder` перед передачей его в класс ответов. +Но если вы уверены, что содержимое, которое вы возвращаете, **сериализуемо с JSON**, вы можете передать его напрямую в класс ответа и избежать дополнительной нагрузки, которую FastAPI имел бы, передавая возвращаемый контент через `jsonable_encoder` перед передачей его в класс ответа. {* ../../docs_src/custom_response/tutorial001b.py hl[2,7] *} /// info | Информация -Параметр `response_class` также будет использоваться для определения "media type" ответа. +Параметр `response_class` также будет использоваться для определения "типа содержимого" ответа. -В этом случае, HTTP заголовок `Content-Type` будет установлен в `application/json`. +В данном случае HTTP-заголовок `Content-Type` будет установлен в `application/json`. И он будет задокументирован как таковой в OpenAPI. @@ -44,24 +44,24 @@ /// tip | Совет -`ORJSONResponse` доступен только в FastAPI, он недоступен в Starlette. +`ORJSONResponse` доступен только в FastAPI, не в Starlette. /// -## HTML Ответ +## HTML-ответ Чтобы вернуть ответ с HTML напрямую из **FastAPI**, используйте `HTMLResponse`. * Импортируйте `HTMLResponse`. -* Передайте `HTMLResponse` как параметр `response_class` вашего *декоратора операции пути*. +* Передайте `HTMLResponse` в качестве параметра `response_class` вашего *декоратора операции пути*. {* ../../docs_src/custom_response/tutorial002.py hl[2,7] *} /// info | Информация -Параметр `response_class` также будет использоваться для определения "media type" ответа. +Параметр `response_class` также будет использоваться для определения "типа содержимого" ответа. -В этом случае, HTTP заголовок `Content-Type` будет установлен в `text/html`. +В этом случае HTTP-заголовок `Content-Type` будет установлен в `text/html`. И он будет задокументирован как таковой в OpenAPI. @@ -69,41 +69,41 @@ ### Возврат `Response` -Как показано в [Возврат ответа напрямую](response-directly.md){.internal-link target=_blank}, вы также можете переопределить ответ напрямую в вашей *операции пути*, возвращая его. +Как показано в разделе [Возврат Response напрямую](response-directly.md){.internal-link target=_blank}, вы также можете переопределить ответ напрямую в вашей *операции пути*, возвращая его. -Тот же самый пример, возвращающий `HTMLResponse`, мог бы выглядеть следующим образом: +Тот же пример, что и выше, возвращающий `HTMLResponse`, может выглядеть так: {* ../../docs_src/custom_response/tutorial003.py hl[2,7,19] *} /// warning | Предупреждение -`Response`, возвращенный напрямую вашей *функцией операции пути*, не будет задокументирован в OpenAPI (например, `Content-Type` не будет документирован) и не будет виден в автоматической интерактивной документации. +`Response`, возвращенный напрямую вашей *функцией-обработчиком пути*, не будет задокументирован в OpenAPI (например, `Content-Type` не будет задокументирован) и не будет виден в автоматически генерируемой интерактивной документации. /// /// info | Информация -Конечно, фактический заголовок `Content-Type`, код статуса и т.д. будут исходить из объекта `Response`, который вы вернули. +Конечно, фактический заголовок `Content-Type`, статус-код и др., будут из объекта `Response`, который вы вернули. /// ### Документирование в OpenAPI и переопределение `Response` -Если вы хотите переопределить ответ внутри функции, но в то же время задокументировать "media type" в OpenAPI, вы можете использовать параметр `response_class` И вернуть объект `Response`. +Если вы хотите переопределить ответ из функции, но при этом документация должна содержать "тип содержимого" в OpenAPI, вы можете использовать параметр `response_class` И вернуть объект `Response`. -`response_class` будет использоваться только для документирования *операции пути* в OpenAPI, но ваш `Response` будет использоваться как есть. +Тогда `response_class` будет использоваться только для документирования OpenAPI *операции пути*, но ваш `Response` будет использоваться как есть. #### Возврат `HTMLResponse` напрямую -Например, это может выглядеть следующим образом: +Например, это может быть что-то вроде: {* ../../docs_src/custom_response/tutorial004.py hl[7,21,23] *} -В этом примере функция `generate_html_response()` уже генерирует и возвращает `Response` вместо возврата HTML в `str`. +В этом примере функция `generate_html_response()` уже генерирует и возвращает `Response` вместо возврата HTML в виде `str`. -Возвращая результат вызова `generate_html_response()`, вы уже возвращаете `Response`, который переопределяет стандартное поведение **FastAPI**. +Возвращая результат вызова `generate_html_response()`, вы уже возвращаете `Response`, который переопределит поведение **FastAPI** по умолчанию. -Но, поскольку вы также передали `HTMLResponse` в `response_class`, **FastAPI** будет знать, как задокументировать это в OpenAPI и интерактивной документации, как HTML с `text/html`: +Но так как вы также передали `HTMLResponse` в `response_class`, **FastAPI** будет знать, как задокументировать это в OpenAPI и интерактивной документации как HTML с `text/html`: @@ -111,72 +111,72 @@ Вот некоторые из доступных ответов. -Имейте в виду, что вы можете использовать `Response`, чтобы вернуть что-либо еще, или даже создать собственный подкласс. +Имейте в виду, что вы можете использовать `Response` для возврата чего-либо еще или даже создать собственный подкласс. -/// note | Технические подробности +/// note | Технические детали -Вы также могли бы использовать `from starlette.responses import HTMLResponse`. +Вы также можете использовать `from starlette.responses import HTMLResponse`. -**FastAPI** предоставляет тот же `starlette.responses` как `fastapi.responses` просто для вашего удобства как разработчика. Но большинство доступных ответов поступают непосредственно из Starlette. +**FastAPI** предоставляет те же `starlette.responses`, что и `fastapi.responses`, просто для вашего удобства, как разработчика. Но большинство доступных ответов поступают напрямую из Starlette. /// ### `Response` -Основной класс `Response`, все другие ответы наследуются от него. +Основной класс `Response`, все остальные ответы наследуются от него. Вы можете вернуть его напрямую. Он принимает следующие параметры: * `content` - `str` или `bytes`. -* `status_code` - `int` HTTP код состояния. +* `status_code` - `int` HTTP статус-код. * `headers` - `dict` строк. -* `media_type` - `str`, указывающая тип носителя. Например, `"text/html"`. +* `media_type` - `str`, который задает тип содержимого, например `"text/html"`. -FastAPI (фактически Starlette) автоматически включит заголовок Content-Length. Также будет включен заголовок Content-Type, основанный на `media_type` и добавлением кодировки для текстовых типов. +FastAPI (фактически Starlette) автоматически добавит заголовок Content-Length. Он также включит заголовок Content-Type, основанный на `media_type` и добавит кодировку для текстовых типов. {* ../../docs_src/response_directly/tutorial002.py hl[1,18] *} ### `HTMLResponse` -Принимает некоторый текст или байты и возвращает HTML ответ, как вы прочли выше. +Принимает текст или байты и возвращает HTML-ответ, как вы прочли выше. ### `PlainTextResponse` -Принимает некоторый текст или байты и возвращает ответ с простым текстом. +Принимает текст или байты и возвращает ответ с простым текстом. {* ../../docs_src/custom_response/tutorial005.py hl[2,7,9] *} ### `JSONResponse` -Принимает некоторые данные и возвращает закодированный ответ `application/json`. +Принимает данные и возвращает ответ, кодированный как `application/json`. -Это стандартный ответ, используемый в **FastAPI**, как вы прочли выше. +Это ответ по умолчанию, используемый в **FastAPI**, как вы прочли выше. ### `ORJSONResponse` -Быстрая альтернатива JSON ответу, используя `orjson`, как вы прочли выше. +Быстрая альтернатива JSON-ответа, использующая `orjson`, как вы прочли выше. /// info | Информация -Это требует установки `orjson`, например с `pip install orjson`. +Для этого требуется установка `orjson`, например с помощью `pip install orjson`. /// ### `UJSONResponse` -Альтернативный JSON ответ, используя `ujson`. +Альтернативный JSON-ответ, использующий `ujson`. /// info | Информация -Это требует установки `ujson`, например с `pip install ujson`. +Для этого требуется установка `ujson`, например с помощью `pip install ujson`. /// /// warning | Предупреждение -`ujson` менее аккуратен по сравнению с встроенной реализацией Python в том, как он обрабатывает некоторые крайние случаи. +`ujson` менее осторожна, чем встроенная реализация Python, в том, как она обрабатывает некоторые крайние случаи. /// @@ -184,13 +184,13 @@ FastAPI (фактически Starlette) автоматически включи /// tip | Совет -Возможно, `ORJSONResponse` может оказаться более быстрой альтернативой. +Возможно, `ORJSONResponse` может быть более быстрой альтернативой. /// ### `RedirectResponse` -Возвращает HTTP переадресацию. Использует код состояния 307 (Временная переадресация) по умолчанию. +Возвращает HTTP-перенаправление. Использует статус-код 307 (Временное перенаправление) по умолчанию. Вы можете вернуть `RedirectResponse` напрямую: @@ -200,60 +200,61 @@ FastAPI (фактически Starlette) автоматически включи Или вы можете использовать его в параметре `response_class`: + {* ../../docs_src/custom_response/tutorial006b.py hl[2,7,9] *} -Если вы сделаете это, тогда вы можете вернуть URL напрямую из вашей *функции операции пути*. +Если вы сделаете это, то можете вернуть URL непосредственно из вашей *функции-обработчика пути*. -В этом случае, используемый `status_code` будет таким же, как стандартный для `RedirectResponse`, который равен `307`. +В этом случае, используемый `status_code` будет тем, что по умолчанию для `RedirectResponse`, а именно `307`. --- -Вы также можете использовать параметр `status_code`, комбинируя его с параметром `response_class`: +Вы также можете использовать параметр `status_code` в сочетании с параметром `response_class`: {* ../../docs_src/custom_response/tutorial006c.py hl[2,7,9] *} ### `StreamingResponse` -Принимает асинхронный генератор или обычный генератор/итератор и потоково передает тело ответа. +Принимает асинхронный генератор или обычный генератор/итератор и отправляет тело ответа в потоке. {* ../../docs_src/custom_response/tutorial007.py hl[2,14] *} -#### Использование `StreamingResponse` с объектами подобными файлам +#### Использование `StreamingResponse` с объектами, похожими на файлы -Если у вас есть объект подобный файлу (например, объект, возвращаемый `open()`), вы можете создать функцию-генератор для итерации по этому объекту подобному файлу. +Если у вас есть объект, похожий на файл (например, объект, возвращаемый `open()`), вы можете создать функцию-генератор для итерации по этому объекту. -Таким образом, вам не придется предварительно полностью загружать его в память, и вы можете передать эту функцию-генератор в `StreamingResponse` и вернуть его. +Таким образом, вам не нужно предварительно загружать все в память, и вы можете передать эту функцию-генератор в `StreamingResponse` и вернуть ее. -Это включает многие библиотеки для работы с облачным хранилищем, обработки видео и другие. +Это включает множество библиотек для взаимодействия с облачным хранилищем, обработки видео и других. {* ../../docs_src/custom_response/tutorial008.py hl[2,10:12,14] *} -1. Это функция-генератор. Это "функция-генератор", потому что внутри содержит `yield` операторы. -2. Используя `with` блок, мы удостоверяемся, что объект подобный файлу закрыт после завершения работы функции-генератора. То есть, после завершения отправки ответа. -3. Этот `yield from` указывает функции итерироваться по объекту `file_like`. А затем, для каждой части итерации, выдавать эту часть как идущую из этой функции-генератора (`iterfile`). +1. Это функция-генератор. Это "функция-генератор", потому что она содержит оператор `yield`. +2. Используя блок `with`, мы обеспечиваем закрытие объекта, похожего на файл, после завершения выполнения функции-генератора. То есть после того, как отправка ответа завершена. +3. Этот `yield from` указывает функции итерироваться по объекту `file_like`. Затем для каждой части, которую итерация проходит, возвращать эту часть из функции-генератора (`iterfile`). - Таким образом, это функция-генератор, которая передает работу по "генерации" чему-то еще внутри себя. + Таким образом, это функция-генератор, которая передает работу по "генерации" чему-то еще во внутренности. - Делая это таким образом, мы можем поместить это в `with` блок и, таким образом, удостовериться, что объект подобный файлу закрыт после завершения. + Делая так, мы можем поместить это в блок `with` и таким образом обеспечить закрытие объекта, похожего на файл, после завершения. /// tip | Совет -Обратите внимание, что здесь, так как мы используем стандартный `open()`, который не поддерживает `async` и `await`, мы объявляем операцию пути с помощью обычной `def`. +Обратите внимание, что здесь, так как мы используем стандартный `open()`, который не поддерживает `async` и `await`, мы объявляем операцию пути с использованием обычного `def`. /// ### `FileResponse` -Асинхронно потоком передает файл в качестве ответа. +Асинхронно отправляет файл в поток как ответ. -Принимает другой набор аргументов для инстанцирования по сравнению с другими типами ответов: +Принимает другой набор аргументов для создания экземпляра, чем другие типы ответов: -* `path` - Путь к файлу для потоковой передачи. -* `headers` - Любые пользовательские заголовки для включения, как словарь. -* `media_type` - Строка, указывающая тип носителя. Если не указан, имя файла или путь будут использованы для определения типа носителя. -* `filename` - Если установлен, это будет включено в ответ `Content-Disposition`. +* `path` - Путь к файлу, который необходимо отправить в поток. +* `headers` - Любые пользовательские заголовки, которые необходимо включить, в виде словаря. +* `media_type` - Строка, задающая тип содержимого. Если не установлено, для определения типа содержимого будет использоваться имя файла или путь. +* `filename` - Если установлено, это будет включено в заголовок `Content-Disposition` ответа. -Ответы с файлами будут включать соответствующие заголовки `Content-Length`, `Last-Modified` и `ETag`. +Ответы на файлы будут включать соответствующие заголовки `Content-Length`, `Last-Modified` и `ETag`. {* ../../docs_src/custom_response/tutorial009.py hl[2,10] *} @@ -261,27 +262,27 @@ FastAPI (фактически Starlette) автоматически включи {* ../../docs_src/custom_response/tutorial009b.py hl[2,8,10] *} -В этом случае вы можете вернуть путь к файлу напрямую из вашей *функции операции пути*. +В этом случае, вы можете вернуть путь к файлу напрямую из вашей *функции-обработчика пути*. -## Пользовательский класс ответа +## Класс пользовательского ответа -Вы можете создать собственный пользовательский класс ответа, наследуясь от `Response` и используя его. +Вы можете создать свой собственный класс пользовательского ответа, наследуя от `Response` и используя его. -Например, давайте скажем, что вы хотите использовать `orjson`, но с некоторыми пользовательскими настройками, которые не используются в включенном классе `ORJSONResponse`. +Например, предположим, вы хотите использовать `orjson`, но с некоторыми пользовательскими настройками, не используемыми в включенном классе `ORJSONResponse`. -Давайте скажем, вы хотите, чтобы он возвращал отформатированный и с отступами JSON, поэтому вы хотите использовать опцию orjson `orjson.OPT_INDENT_2`. +Допустим, вы хотите, чтобы он возвращал JSON с отступами и форматированием, поэтому вы хотите использовать опцию orjson `orjson.OPT_INDENT_2`. -Вы могли бы создать `CustomORJSONResponse`. Основное, что вам нужно сделать, это создать метод `Response.render(content)`, который возвращает содержимое в виде `bytes`: +Вы могли бы создать `CustomORJSONResponse`. Главное, что вам нужно сделать, это создать метод `Response.render(content)`, который возвращает содержимое как `bytes`: {* ../../docs_src/custom_response/tutorial009c.py hl[9:14,17] *} -Теперь вместо возврата: +Теперь вместо возвращения: ```json {"message": "Hello World"} ``` -...этот ответ будет возвращать: +...этот ответ вернет: ```json { @@ -289,24 +290,24 @@ FastAPI (фактически Starlette) автоматически включи } ``` -Конечно, вы, вероятно, найдете гораздо лучшие способы использовать это, чем просто форматирование JSON. 😉 +Конечно, вы, вероятно, найдете гораздо лучшие способы использовать это, чем форматирование JSON. 😉 ## Класс ответа по умолчанию При создании экземпляра класса **FastAPI** или `APIRouter` вы можете указать, какой класс ответа использовать по умолчанию. -Параметр, который определяет это — `default_response_class`. +Параметр, который это определяет, называется `default_response_class`. -В примере ниже, **FastAPI** будет использовать `ORJSONResponse` по умолчанию, во всех *операциях пути*, вместо `JSONResponse`. +В приведенном ниже примере **FastAPI** будет использовать `ORJSONResponse` по умолчанию во всех *операциях пути* вместо `JSONResponse`. {* ../../docs_src/custom_response/tutorial010.py hl[2,4] *} /// tip | Совет -Вы все равно можете переопределить `response_class` в *операциях пути* как прежде. +Вы все еще можете переопределять `response_class` в *операциях пути*, как и раньше. /// ## Дополнительная документация -Вы также можете объявить тип носителя и многие другие детали в OpenAPI, используя `responses`: [Дополнительные ответы в OpenAPI](additional-responses.md){.internal-link target=_blank}. +Вы также можете объявить тип содержимого и многие другие детали в OpenAPI, используя `responses`: [Дополнительные ответы в OpenAPI](additional-responses.md){.internal-link target=_blank}. diff --git a/docs/ru/docs/advanced/dataclasses.md b/docs/ru/docs/advanced/dataclasses.md index 95dbb8831..b82469a09 100644 --- a/docs/ru/docs/advanced/dataclasses.md +++ b/docs/ru/docs/advanced/dataclasses.md @@ -1,95 +1,95 @@ # Использование Dataclasses -FastAPI построен на **Pydantic**, и я показывал вам, как использовать модели Pydantic для объявления запросов и ответов. +FastAPI построен на основе **Pydantic**, и я уже показывал вам, как использовать модели Pydantic для объявления HTTP-запросов и HTTP-ответов. Но FastAPI также поддерживает использование `dataclasses` таким же образом: {* ../../docs_src/dataclasses/tutorial001.py hl[1,7:12,19:20] *} -Это все еще поддерживается благодаря **Pydantic**, так как он имеет внутреннюю поддержку `dataclasses`. +Это по-прежнему поддерживается благодаря **Pydantic**, так как в нем есть внутренняя поддержка `dataclasses`. -Таким образом, даже с кодом выше, который не использует Pydantic явно, FastAPI использует Pydantic для преобразования этих стандартных `dataclasses` в собственный вариант `dataclasses` от Pydantic. +Итак, даже с приведенным выше кодом, который явно не использует Pydantic, FastAPI использует Pydantic для преобразования стандартных dataclasses в собственный вариант dataclasses от Pydantic. -И, конечно, это поддерживает то же самое: +И, конечно же, он поддерживает то же самое: -* валидацию данных -* сериализацию данных -* документацию данных и т. д. +* валидация данных +* сериализация данных +* документация данных и т.д. -Это работает так же, как и с моделями Pydantic. И фактически это достигается тем же способом, внутрь посредством Pydantic. +Это работает так же, как и с моделями Pydantic. И это фактически достигается таким же образом, под капотом, с использованием Pydantic. /// info | Информация -Имейте в виду, что dataclasses не могут сделать все, что могут модели Pydantic. +Имейте в виду, что dataclasses не могут выполнять все то, что могут делать модели Pydantic. -Поэтому вам все равно может понадобиться использовать модели Pydantic. +Поэтому, возможно, вам все равно придется использовать модели Pydantic. -Но если у вас есть несколько `dataclasses`, это хороший трюк, чтобы использовать их для питания веб-API с помощью FastAPI. 🤓 +Но если у вас есть много dataclasses, это отличный трюк, чтобы использовать их для создания веб-API с помощью FastAPI. 🤓 /// ## Dataclasses в `response_model` -Вы можете также использовать `dataclasses` в параметре `response_model`: +Вы также можете использовать `dataclasses` в параметре `response_model`: {* ../../docs_src/dataclasses/tutorial002.py hl[1,7:13,19] *} -Dataclass будет автоматически преобразован в dataclass Pydantic. +Dataclass будет автоматически преобразован в Pydantic dataclass. -Таким образом, его схема будет отображаться в пользовательском интерфейсе API документации: +Таким образом, его схема будет отображаться в интерфейсе документации API: -## Dataclasses в вложенных структурах данных +## Dataclasses в Вложенных Структурах Данных -Вы также можете комбинировать `dataclasses` с другими аннотациями типов, чтобы создавать вложенные структуры данных. +Вы также можете комбинировать `dataclasses` с другими аннотациями типов для создания вложенных структур данных. -В некоторых случаях вам все же может понадобиться использовать версию `dataclasses` от Pydantic. Например, если у вас возникают ошибки с автоматически сгенерированной документацией API. +В некоторых случаях, возможно, вам все равно придется использовать версию `dataclasses` от Pydantic. Например, если у вас возникли ошибки с автоматической генерацией документации API. -В этом случае вы можете просто заменить стандартные `dataclasses` на `pydantic.dataclasses`, что является полноценной заменой: +В этом случае вы можете просто заменить стандартные `dataclasses` на `pydantic.dataclasses`, что является заменой "на лету": {* ../../docs_src/dataclasses/tutorial003.py hl[1,5,8:11,14:17,23:25,28] *} 1. Мы по-прежнему импортируем `field` из стандартных `dataclasses`. -2. `pydantic.dataclasses` является полноценной заменой для `dataclasses`. +2. `pydantic.dataclasses` является заменой "на лету" для `dataclasses`. -3. Dataclass `Author` включает в себя список `Item` dataclasses. +3. Dataclass `Author` включает список dataclasses `Item`. 4. Dataclass `Author` используется как параметр `response_model`. -5. Вы можете использовать другие стандартные аннотации типов с dataclasses в качестве тела запроса. +5. Вы можете использовать другие стандартные аннотации типов с dataclasses как HTTP-тело запроса. - В этом случае это список `Item` dataclasses. + В этом случае это список dataclasses `Item`. -6. Здесь мы возвращаем словарь, содержащий `items`, который представляет собой список dataclasses. +6. Здесь мы возвращаем словарь, содержащий `items`, который является списком dataclasses. - FastAPI все еще способен сериализовать данные в JSON. + FastAPI по-прежнему способен сериализовать данные в JSON. -7. Здесь `response_model` использует аннотацию типа списка `Author` dataclasses. +7. Здесь `response_model` использует аннотацию типа список dataclasses `Author`. - Опять же, вы можете сочетать `dataclasses` с стандартными аннотациями типов. + Снова вы можете комбинировать `dataclasses` с стандартными аннотациями типов. -8. Обратите внимание, что эта *функция операции пути* использует обычный `def` вместо `async def`. +8. Обратите внимание, что эта *функция-обработчик пути* использует обычный `def` вместо `async def`. - Как всегда, в FastAPI вы можете комбинировать `def` и `async def` по мере необходимости. + Как всегда, в FastAPI вы можете сочетать `def` и `async def` в зависимости от необходимости. - Если вам нужно повторить, когда использовать что, взгляните на раздел _"В спешке?"_ в документации о [`async` и `await`](../async.md#in-a-hurry){.internal-link target=_blank}. + Если вы забыли, когда использовать какой, посмотрите раздел _"Нет времени?"_ в документации о [`async` и `await`](../async.md#in-a-hurry){.internal-link target=_blank}. -9. Эта *функция операции пути* не возвращает dataclasses (хотя могла бы), а список словарей с внутренними данными. +9. Эта *функция-обработчик пути* не возвращает dataclasses (хотя могла бы), а список словарей с внутренними данными. - FastAPI использует параметр `response_model` (который включает dataclasses) для преобразования ответа. + FastAPI будет использовать параметр `response_model` (который включает dataclasses), чтобы преобразовать ответ. -Вы можете комбинировать `dataclasses` с другими аннотациями типов во множестве различных комбинаций для формирования сложных структур данных. +Вы можете комбинировать `dataclasses` с другими аннотациями типов в различных комбинациях, чтобы формировать сложные структуры данных. -Проверьте советы по аннотациям в коде выше, чтобы увидеть более конкретные детали. +Посмотрите советы по аннотации в коде выше, чтобы узнать больше деталей. ## Узнать больше -Вы также можете комбинировать `dataclasses` с другими моделями Pydantic, наследовать от них, включать их в свои собственные модели и т. д. +Вы также можете комбинировать `dataclasses` с другими моделями Pydantic, наследовать их, включать их в свои собственные модели и т.д. Чтобы узнать больше, ознакомьтесь с документацией Pydantic о dataclasses. ## Версия -Это доступно с версии FastAPI `0.67.0`. 🔖 +Это доступно начиная с версии FastAPI `0.67.0`. 🔖 diff --git a/docs/ru/docs/advanced/events.md b/docs/ru/docs/advanced/events.md index 9a4ed3219..ac5b8affd 100644 --- a/docs/ru/docs/advanced/events.md +++ b/docs/ru/docs/advanced/events.md @@ -1,86 +1,86 @@ # События жизненного цикла -Вы можете определить логику (код), которая должна выполняться перед тем, как приложение **запустится**. Это означает, что этот код будет выполнен **один раз**, **до** того как приложение **начнет принимать запросы**. +Вы можете определить логику (код), которая должна быть выполнена перед запуском приложения. Это значит, что данный код будет выполнен **единожды**, **перед** тем, как приложение **начнет принимать HTTP-запросы**. -Таким же образом, вы можете определить логику (код), которая должна выполняться при **завершении работы** приложения. В этом случае этот код будет выполнен **один раз**, **после** обработки возможных **многочисленных запросов**. +Аналогично, вы можете определить логику (код), которая должна быть выполнена при остановке приложения. В этом случае код будет выполнен **единожды**, **после** обработки, возможно, **множества HTTP-запросов**. -Так как этот код выполняется до того, как приложение **начнет** принимать запросы, и сразу после того как оно **закончит** их обрабатывать, он покрывает весь **жизненный цикл** приложения (слово "жизненный цикл" будет важно через секунду 😉). +Поскольку этот код выполняется до того, как приложение **начинает** принимать запросы, и непосредственно после того, как оно **заканчивает** обработку запросов, он охватывает весь **lifespan** приложения (слово "lifespan" сейчас станет важным 😉). -Это может быть очень полезно для настройки **ресурсов**, которые вам нужно использовать для всего приложения, и которые **разделяются** между запросами, и/или которые нужно **очистить** впоследствии. Например, пул соединений с базой данных или загрузка общего алгоритма машинного обучения. +Это может быть очень полезно для настройки **ресурсов**, которые вам нужно использовать для всего приложения, и которые **разделяются** между запросами, и/или которые требуют **освобождения** после завершения работы. Например, пул подключений к базе данных или загрузка общей модели машинного обучения. ## Пример использования -Начнем с примера **использования**, а затем посмотрим, как это решить. +Давайте начнем с примера **использования**, а затем посмотрим, как его решить. -Представьте, что у вас есть несколько **моделей машинного обучения**, которые вы хотите использовать для обработки запросов. 🤖 +Предположим, у вас есть несколько **моделей машинного обучения**, которые вы хотите использовать для обработки запросов. 🤖 -Эти же модели разделяются между запросами, так что это не одна модель на запрос или одна на пользователя или что-то подобное. +Те же самые модели разделяются между всеми запросами, то есть это не одна модель на запрос или одна на пользователя или что-то подобное. -Представьте, что загрузка модели может **занимать довольно много времени**, потому что ей нужно прочесть много **данных с диска**. Поэтому вы не хотите делать это для каждого запроса. +Представим, что загрузка модели может **занять значительное время**, потому что необходимо прочитать много **данных с диска**. Поэтому вы не хотите делать это для каждого запроса. -Вы могли бы загрузить её на верхнем уровне модуля/файла, но это также означало бы, что модель будет **загружена**, даже если вы просто запускаете простой автоматический тест, и тогда этот тест будет **медленным**, потому что ему придется ждать загрузки модели перед выполнением независимой части кода. +Вы можете загрузить ее на верхнем уровне модуля/файла, но это также означало бы, что модель **загрузится**, даже если вы просто запускаете простой автоматизированный тест, и такой тест был бы **медленный**, так как пришлось бы ждать, пока модель загрузится, прежде чем можно было бы выполнить независимую часть кода. -Вот это мы и решим: загрузим модель перед обработкой запросов, но только прямо перед тем, как приложение начнёт принимать запросы, а не во время загрузки кода. +Это то, что мы решаем: давайте загрузим модель до того, как запросы начнут обрабатываться, но только непосредственно перед тем, как приложение начнет принимать запросы, а не в процессе загрузки кода. -## Жизненный цикл +## Lifespan -Вы можете определить логику для *запуска* и *завершения работы* с использованием параметра `lifespan` приложения `FastAPI` и "контекстного менеджера" (я покажу вам, что это такое, через секунду). +Вы можете определить эту логику *запуска* и *выключения* с помощью параметра `lifespan` в приложении `FastAPI` и "менеджера контекста" (я покажу вам, что это такое, через мгновение). -Начнем с примера, а затем рассмотрим его подробно. +Давайте начнем с примера и затем разберем его подробно. -Мы создаем асинхронную функцию `lifespan()` с использованием `yield`, как показано ниже: +Создаем асинхронную функцию `lifespan()` с `yield` следующим образом: {* ../../docs_src/events/tutorial003.py hl[16,19] *} -Здесь мы симулируем дорогую *операцию старта* загрузки модели, помещая (фейковую) функцию модели в словарь с моделями машинного обучения до `yield`. Этот код будет выполнен **до** того, как приложение **начнет принимать запросы**, в момент *старта*. +Здесь мы симулируем дорогостоящую операцию *запуска*, загружая модель, помещая (фальшивую) функцию модели в словарь с моделями машинного обучения перед `yield`. Этот код будет выполнен **до** того, как приложение **начнет принимать запросы**, в процессе *запуска*. -А затем, сразу после `yield`, мы выгружаем модель. Этот код будет выполнен **после** того, как приложение **закончит обрабатывать запросы**, прямо перед *завершением работы*. Это может, например, освободить такие ресурсы, как память или GPU. +И затем, сразу после `yield`, мы выгружаем модель. Этот код будет выполнен **после** того, как приложение **завершит обработку запросов**, непосредственно перед *выключением*. Это может, например, освободить такие ресурсы, как память или GPU. /// tip | Совет -Завершение работы происходит, когда вы **останавливаете** приложение. +Выключение происходит, когда вы **останавливаете** приложение. -Возможно, вам нужно запустить новую версию или вы просто устали его запускать. 🤷 +Возможно, вам нужно запустить новую версию, или вы просто устали от его работы. 🤷 /// -### Функция жизненного цикла +### Функция Lifespan -Первое, на что стоит обратить внимание, это то, что мы определяем асинхронную функцию с `yield`. Это очень похоже на зависимости с `yield`. +Первое, что следует заметить, это то, что мы определяем асинхронную функцию с `yield`. Это очень похоже на зависимости с `yield`. {* ../../docs_src/events/tutorial003.py hl[14:19] *} -Первая часть функции, до `yield`, будет выполнена **до** того, как приложение стартует. +Первая часть функции, до `yield`, будет выполнена **до** того, как приложение начнет свою работу. -А часть после `yield` будет выполнена **после** того, как приложение завершит работу. +А часть после `yield` будет выполнена **после** завершения работы приложения. -### Асинхронный контекстный менеджер +### Асинхронный менеджер контекста -Если вы посмотрите, то заметите, что функция декорирована с помощью `@asynccontextmanager`. +Если вы посмотрите, функция декорирована с помощью `@asynccontextmanager`. -Это преобразует функцию в то, что называется "**асинхронным контекстным менеджером**". +Это преобразует функцию в нечто, называемое "**асинхронным менеджером контекста**". {* ../../docs_src/events/tutorial003.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): await do_stuff() ``` -Когда вы создаете контекстный менеджер или асинхронный контекстный менеджер, как выше, он делает так, что, прежде чем войти в блок `with`, будет выполнен код перед `yield`, а после выхода из блока `with`, будет выполнен код после `yield`. +Когда вы создаете менеджер контекста или асинхронный менеджер контекста, как выше, его работа заключается в том, что, до входа в блок `with`, он выполняет код перед `yield`, и после выхода из блока `with`, он выполняет код после `yield`. В нашем примере кода выше мы не используем его напрямую, но передаем его FastAPI для использования. -Параметр `lifespan` приложения `FastAPI` принимает **асинхронный контекстный менеджер**, так что мы можем передать ему наш новый асинхронный контекстный менеджер `lifespan`. +Параметр `lifespan` приложения `FastAPI` принимает **асинхронный менеджер контекста**, так что мы можем передать ему наш новый асинхронный менеджер контекста `lifespan`. {* ../../docs_src/events/tutorial003.py hl[22] *} @@ -88,78 +88,78 @@ async with lifespan(app): /// warning | Предупреждение -Рекомендуемый способ управления *запуском* и *завершением работы* — использовать параметр `lifespan` приложения `FastAPI`, как описано выше. Если вы предоставите параметр `lifespan`, обработчики событий `startup` и `shutdown` больше не будут вызываться. Используются либо `lifespan`, либо событийные обработчики, но не оба. +Рекомендуемый способ обработки *запуска* и *выключения* — это использование параметра `lifespan` приложения `FastAPI`, как описано выше. Если вы предоставите параметр `lifespan`, обработчики событий `startup` и `shutdown` больше не будут вызываться. Вы можете использовать либо `lifespan`, либо события, но не оба. -Вы, вероятно, можете пропустить эту часть. +Эту часть можно, вероятно, пропустить. /// -Существует альтернативный способ определения этой логики для выполнения в момент *запуска* и *завершения работы*. +Существует альтернативный способ определения логики, которая будет выполнена во время *запуска* и во время *выключения*. -Вы можете определить обработчики событий (функции), которые должны быть выполнены до запуска приложения, или при завершении работы приложения. +Вы можете определить обработчики событий (функции), которые необходимо выполнить до запуска приложения или при его остановке. -Эти функции могут быть объявлены с `async def` или обычными `def`. +Эти функции могут быть объявлены как `async def`, так и обычный `def`. ### Событие `startup` -Чтобы добавить функцию, которая должна выполняться перед началом работы приложения, объявите её с событием `"startup"`: +Чтобы добавить функцию, которую следует запустить перед запуском приложения, объявите ее с событием `"startup"`: {* ../../docs_src/events/tutorial001.py hl[8] *} -В этом случае функция-обработчик события `startup` инициализирует "базу данных" элементов (это просто `dict`) с некоторыми значениями. +В этом случае функция-обработчик события `startup` инициализирует "базу данных" элементов (просто `dict`) с некоторыми значениями. -Можно добавить более одной функции-обработчика события. +Вы можете добавить более одной функции-обработчика события. -И ваше приложение не начнет принимать запросы, пока не завершатся все обработчики события `startup`. +И ваше приложение не начнет принимать запросы до тех пор, пока все обработчики событий `startup` не будут выполнены. ### Событие `shutdown` -Чтобы добавить функцию, которая должна выполняться при завершении работы приложения, объявите её с событием `"shutdown"`: +Чтобы добавить функцию, которую следует запустить при остановке приложения, объявите ее с событием `"shutdown"`: {* ../../docs_src/events/tutorial002.py hl[6] *} -Здесь функция-обработчик события `shutdown` запишет текстовую строку `"Application shutdown"` в файл `log.txt`. +Здесь функция-обработчик события `shutdown` запишет строку текста `"Application shutdown"` в файл `log.txt`. /// info | Информация -В функции `open()`, параметр `mode="a"` означает "добавление", то есть строка будет добавлена после того, что уже есть в файле, без перезаписи предыдущего содержимого. +В функции `open()`, `mode="a"` означает "добавить", так что строка будет добавлена после того, что уже есть в этом файле, без перезаписи предыдущего содержимого. /// /// tip | Совет -Обратите внимание, что в этом случае мы используем стандартную функцию Python `open()`, которая взаимодействует с файлом. +Обратите внимание, что в данном случае мы используем стандартную функцию Python `open()`, которая взаимодействует с файлом. -Таким образом, это включает ввод/вывод (I/O), который требует "ожидания", чтобы данные были записаны на диск. +Таким образом, это включает в себя ввод/вывод (I/O), который требует "ожидания" для записи данных на диск. Но `open()` не использует `async` и `await`. -Поэтому мы объявляем функцию-обработчик событий с использованием стандартного `def` вместо `async def`. +Поэтому мы объявляем функцию-обработчик события как стандартный `def` вместо `async def`. /// ### `startup` и `shutdown` вместе -Существует высокая вероятность того, что логика вашего *запуска* и *завершения работы* связана; возможно, вы хотите что-то начать, а затем завершить, получить ресурс, а потом его освободить и т.д. +Существует большая вероятность, что логика ваших *запуска* и *выключения* связана; возможно, вы хотите что-то запустить, а затем завершить, получить ресурс, а затем освободить его и т. д. -Выполнение этого в отдельных функциях, которые не разделяют логику или переменные, сложнее, поскольку вам нужно будет сохранять значения в глобальных переменных или использовать подобные трюки. +Делать это в раздельных функциях, которые не используют совместно логику или переменные, сложнее, так как придется сохранять значения в глобальных переменных или использовать подобные уловки. -По этой причине теперь рекомендуется вместо этого использовать `lifespan`, как объяснено выше. +Из-за этого теперь рекомендуется вместо этого использовать `lifespan`, как объяснено выше. ## Технические детали -Просто техническая деталь для любопытных. 🤓 +Просто техническая деталь для любознательных гиков. 🤓 -В ASGI технической спецификации это часть оглашения Жизненного Цикла, и она определяет события `startup` и `shutdown`. +В основе, в технической спецификации ASGI, это часть Протокола Lifespan, и он определяет события, называемые `startup` и `shutdown`. /// info | Информация -Вы можете прочитать больше о обработчиках `lifespan` в Starlette в документации Starlette's Lifespan. +Вы можете прочитать больше об обработчиках `lifespan` в Starlette в документации "Lifespan" Starlette. -В том числе то, как справляться с состоянием жизненного цикла, которое может быть использовано в других областях вашего кода. +Включая информацию о том, как обрабатывать состояние lifespan, которое может быть использовано в других частях вашего кода. /// -## Подпрограммы +## Подприложения -🚨 Помните, что эти события жизненного цикла (startup и shutdown) будут выполнены только для основного приложения, а не для [Подпрограмм - Монтирования](sub-applications.md){.internal-link target=_blank}. +🚨 Помните, что эти события жизненного цикла (запуска и завершения) будут выполнены только для основного приложения, а не для [подприложений - монтировок](sub-applications.md){.internal-link target=_blank}. diff --git a/docs/ru/docs/advanced/generate-clients.md b/docs/ru/docs/advanced/generate-clients.md index eae0bc432..7e8e274c1 100644 --- a/docs/ru/docs/advanced/generate-clients.md +++ b/docs/ru/docs/advanced/generate-clients.md @@ -1,60 +1,60 @@ # Генерация клиентов -Так как **FastAPI** основан на спецификации OpenAPI, вы получаете автоматическую совместимость со многими инструментами, включая автоматическую документацию API (предоставленную Swagger UI). +Так как **FastAPI** основан на спецификации OpenAPI, вы автоматически получаете совместимость со многими инструментами, включая автоматическую документацию API (предоставляемую Swagger UI). -Одним из преимуществ, не всегда очевидных, является возможность **генерировать клиентов** (иногда их называют **SDK**) для вашего API на различных **языках программирования**. +Один конкретный плюс, который не всегда очевиден, заключается в том, что вы можете **сгенерировать клиентов** (иногда их называют **SDKs** ) для вашего API для многих разных **языков программирования**. ## Генераторы клиентов OpenAPI Существует множество инструментов для генерации клиентов из **OpenAPI**. -Распространённый инструмент - это OpenAPI Generator. +Один из популярных инструментов — это OpenAPI Generator. -Если вы создаёте **фронтенд**, отличной альтернативой является openapi-ts. +Если вы создаете **фронтенд**, очень интересной альтернативой является openapi-ts. -## Генераторы клиентов и SDK - спонсор +## Генераторы клиентов и SDK - спонсоры -Существуют также некоторые **поддерживаемые компаниями** генераторы клиентов и SDK на базе OpenAPI (FastAPI), которые в некоторых случаях могут предложить вам **дополнительные функции** поверх высококачественно сгенерированных SDK/клиентов. +Существуют также некоторые **поддерживаемые компаниями** генераторы клиентов и SDK, основанные на OpenAPI (FastAPI), в некоторых случаях они могут предложить вам **дополнительные функции** поверх высококачественных сгенерированных SDK/клиентов. -Некоторые из них также ✨ [**спонсируют FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, что обеспечивает продолжение и здоровое **развитие** FastAPI и его **экосистемы**. +Некоторые из них также ✨ [**спонсируют FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, что обеспечивает продолжительное и здоровое **развитие** FastAPI и его **экосистемы**. -Это показывает их истинную приверженность FastAPI и его **сообществу** (вам), ведь они не только хотят предоставить вам **хороший сервис**, но и хотят убедиться, что у вас есть **хороший и здоровый фреймворк**, FastAPI. 🙇 +Это также демонстрирует их истинную приверженность FastAPI и его **сообществу** (вам), ведь они не только хотят предоставить вам **качественное обслуживание**, но и стремятся обеспечить вам **качественный и здоровый фреймворк**, FastAPI. 🙇 -Например, вы можете попробовать: +Например, вам может быть интересно попробовать: * Speakeasy * Stainless * liblab -Существуют также другие компании, предлагающие аналогичные услуги, которые вы можете найти и изучить в сети. 🤓 +Также существует несколько других компаний, предлагающих аналогичные услуги, которые вы можете найти в интернете. 🤓 -## Генерация TypeScript клиента для фронтенда +## Генерация TypeScript-клиента для фронтенда -Начнём с простого приложения на FastAPI: +Давайте начнем с простой FastAPI-программы: {* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *} -Обратите внимание, что *операции пути* определяют модели, которые они используют для запросов и ответов, используя модели `Item` и `ResponseMessage`. +Обратите внимание, что *операции пути* определяют модели, которые они используют для полезной нагрузки запроса и ответа, используя модели `Item` и `ResponseMessage`. ### Документация API -Если вы перейдёте к документации API, вы увидите, что она содержит **схемы** для данных, которые должны быть отправлены в запросах и получены в ответах: +Если вы перейдете к документации API, вы увидите, что в ней содержатся **схемы** для данных, которые должны быть отправлены в запросах и получены в ответах: -Вы можете увидеть эти схемы, так как они были объявлены с использованием моделей в приложении. +Вы видите эти схемы, потому что они были объявлены с моделями в приложении. Эта информация доступна в **схеме OpenAPI** приложения и затем отображается в документации API (с помощью Swagger UI). -И эта же информация из моделей, включённых в OpenAPI, может быть использована для **генерации кода клиента**. +И эта же информация из моделей, включенных в OpenAPI, может быть использована для **генерации кода клиента**. -### Генерация клиента на TypeScript +### Генерация TypeScript-клиента Теперь, когда у нас есть приложение с моделями, мы можем сгенерировать код клиента для фронтенда. -#### Установить `openapi-ts` +#### Установка `openapi-ts` -Вы можете установить `openapi-ts` в код вашего фронтенда с помощью: +Вы можете установить `openapi-ts` в код своего фронтенда с помощью:
@@ -66,11 +66,11 @@ $ npm install @hey-api/openapi-ts --save-dev
-#### Генерация клиентского кода +#### Генерация кода клиента -Для генерации клиентского кода вы можете использовать приложение командной строки `openapi-ts`, которое теперь будет установлено. +Чтобы сгенерировать код клиента, вы можете использовать командное приложение `openapi-ts`, которое теперь будет установлено. -Поскольку оно установлено в локальном проекте, вы, вероятно, не сможете вызывать эту команду напрямую, но сможете прописать её в файле `package.json`. +Поскольку оно установлено в локальном проекте, вы, вероятно, не сможете вызвать эту команду напрямую, но вы можете поместить её в свой файл `package.json`. Он может выглядеть следующим образом: @@ -105,106 +105,106 @@ frontend-app@1.0.0 generate-client /home/user/code/frontend-app -Эта команда сгенерирует код в `./src/client` и будет использовать `axios` (библиотеку HTTP для фронтенда). +Эта команда сгенерирует код в `./src/client` и будет использовать `axios` (фронтенд HTTP-библиотеку) для внутренних нужд. -### Попробуйте использовать клиентский код +### Попробуйте код клиента -Теперь вы можете импортировать и использовать клиентский код, это может выглядеть так, обратите внимание, что вы получите автодополнение для методов: +Теперь вы можете импортировать и использовать код клиента, он может выглядеть следующим образом, обратите внимание, что вы получаете автозавершение для методов: -Вы также получите автодополнение для отправляемых данных: +Вы также получите автозавершение для отправляемой полезной нагрузки: /// tip | Совет -Обратите внимание на автодополнение для `name` и `price`, которые были определены в приложении FastAPI в модели `Item`. +Обратите внимание на автозавершение для `name` и `price`, которые были определены в приложении FastAPI, в модели `Item`. /// -У вас будут встроенные ошибки для данных, которые вы отправляете: +Вы получите ошибки на лету для данных, которые вы отправляете: -Объект ответа также будет иметь автодополнение: +Объект-ответ также будет иметь автозавершение: -## Приложение FastAPI с тегами +## FastAPI-приложение с тегами -Во многих случаях ваше приложение FastAPI будет более крупным, и, вероятно, вы будете использовать теги для разделения различных групп *операций пути*. +Во многих случаях ваше FastAPI-приложение будет больше, и вы, скорее всего, будете использовать теги для разделения разных групп *операций пути*. -Например, у вас может быть раздел для **элементов** и другой раздел для **пользователей**, и они могут быть отделены тегами: +Например, у вас может быть раздел для **товаров** и другой раздел для **пользователей**, и они могут быть разделены с помощью тегов: {* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *} -### Генерация TypeScript клиента с тегами +### Генерация TypeScript-клиента с тегами -Если вы генерируете клиента для приложения FastAPI, использующего теги, это обычно также разделит клиентский код на основе тегов. +Если вы генерируете клиента для FastAPI-приложения с использованем тегов, то обычно клиентский код также будет разделен по тегам. -Таким образом, вы сможете правильно упорядочить и сгруппировать код клиента: +Таким образом, вы сможете правильно упорядочить и сгруппировать клиентский код: -В этом случае у вас есть: +В данном случае у вас есть: * `ItemsService` * `UsersService` -### Имена клиентских методов +### Имена методов клиента -В настоящий момент сгенерированные имена методов, такие как `createItemItemsPost`, выглядят не очень чисто: +Сейчас сгенерированные имена методов, такие как `createItemItemsPost`, не выглядят очень чистыми: ```TypeScript ItemsService.createItemItemsPost({name: "Plumbus", price: 5}) ``` -... это потому, что генератор клиента использует внутренний **идентификатор операции** OpenAPI для каждой *операции пути*. +...это потому, что генератор клиента использует внутренний **идентификатор операции** OpenAPI для каждой *операции пути*. -OpenAPI требует, чтобы каждый идентификатор операции был уникальным для всех *операций пути*, поэтому FastAPI использует **имя функции**, **путь** и **HTTP метод/операцию** для генерации этого идентификатора операции, так как это позволяет убедиться, что идентификаторы операций уникальны. +OpenAPI требует, чтобы каждый идентификатор операции был уникальным среди всех *операций пути*, поэтому FastAPI использует **название функции**, **путь** и **метод/операцию HTTP** для генерации этого идентификатора операции, поскольку таким образом он может обеспечить уникальность идентификаторов операций. -Но я покажу вам, как это улучшить. 🤓 +Но я покажу вам, как улучшить это. 🤓 -## Настраиваемые идентификаторы операций и улучшенные имена методов +## Пользовательские идентификаторы операций и лучшие имена методов -Вы можете **изменить** способ генерации этих идентификаторов операций, чтобы сделать их проще и получить **более простые имена методов** в клиентах. +Вы можете **изменить** способ **генерации** этих идентификаторов операций, чтобы упростить их и получить **более простые названия методов** в клиентах. -В этом случае вам придётся обеспечить уникальность каждого идентификатора операции другим способом. +В этом случае вы должны обеспечить уникальность каждого идентификатора операции другим способом. -Например, вы можете удостовериться, что каждая *операция пути* имеет тег, а затем генерировать идентификатор операции на основе **тега** и **имени** операции пути (имени функции). +Например, вы можете убедиться, что каждая *операция пути* имеет тег, а затем генерировать идентификатор операции на основе **тега** и **названия операции пути** (названия функции). -### Настраиваемая функция генерации уникального идентификатора +### Пользовательская функция генерации уникального идентификатора -FastAPI использует **уникальный идентификатор** для каждой *операции пути*, он используется для **идентификатора операции**, а также для имен необходимых пользовательских моделей, для запросов или ответов. +FastAPI использует **уникальный ID** для каждой *операции пути*, он используется для **идентификатора операции**, а также для имен любых необходимых пользовательских моделей для запросов или ответов. Вы можете настроить эту функцию. Она принимает `APIRoute` и возвращает строку. -Например, здесь используется первый тег (вероятно, у вас будет только один тег) и имя операции пути (имя функции). +Например, здесь используется первый тег (обычно у вас будет только один тег) и название *операции пути* (название функции). -Вы можете передать эту пользовательскую функцию в **FastAPI** как параметр `generate_unique_id_function`: +Вы можете передать эту пользовательскую функцию **FastAPI** в параметре `generate_unique_id_function`: {* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *} -### Генерация TypeScript клиента с пользовательскими идентификаторами операций +### Генерация TypeScript-клиента с пользовательскими идентификаторами операций -Теперь, если вы снова сгенерируете клиента, вы увидите, что у него улучшенные имена методов: +Теперь, если вы снова сгенерируете клиент, вы увидите, что у него улучшенные названия методов: -Как видите, имена методов теперь включают тег и имя функции, они больше не содержат информацию из URL пути и HTTP операции. +Как видите, названия методов теперь содержат тег, а затем имя функции, теперь они не включают информацию из URL-пути и HTTP-операции. -### Предварительная обработка спецификации OpenAPI для генерации клиента +### Предобработка спецификации OpenAPI для генератора клиентов -Сгенерированный код всё ещё содержит некоторую **дублированную информацию**. +Сгенерированный код все равно содержит некоторую **дублирующую информацию**. -Мы уже знаем, что этот метод связан с **items** (элементами), так как это слово содержится в `ItemsService` (взятом из тега), но у нас всё ещё есть название тега в начале имени метода. 😕 +Мы уже знаем, что этот метод связан с **товарами (items)**, потому что это слово появилось в `ItemsService` (взято из тега), но у нас все равно есть имя тега в имени метода. 😕 -Возможно, мы всё же захотим оставить его для OpenAPI в целом, так как это обеспечит уникальность идентификаторов операций. +Вероятно, мы все равно захотим сохранить это для OpenAPI в целом, так как это обеспечит **уникальность** идентификаторов операций. -Но для сгенерированного клиента мы могли бы **изменить** идентификаторы операций OpenAPI прямо перед генерацией клиентов, чтобы сделать имена методов более красивыми и **чистыми**. +Но для сгенерированного клиента мы можем **изменить** идентификаторы операций OpenAPI прямо перед генерацией клиентов, только чтобы сделать эти названия методов более приятными и **чистыми**. -Мы могли бы загрузить JSON OpenAPI в файл `openapi.json`, а затем могли бы **удалить этот префиксированный тег** при помощи скрипта, как здесь: +Мы можем загрузить OpenAPI JSON в файл `openapi.json`, а затем **удалить** этот префикс тега с помощью такого скрипта: {* ../../docs_src/generate_clients/tutorial004.py *} @@ -216,11 +216,11 @@ FastAPI использует **уникальный идентификатор** //// -Благодаря этому идентификаторы операций будут переименованы из `items-get_items` в просто `get_items`, что позволит генератору клиента создать более простые имена методов. +Таким образом, идентификаторы операций будут переименованы из `items-get_items` в просто `get_items`, так генератор клиентов сможет генерировать более простые имена методов. -### Генерация TypeScript клиента с предварительно обработанным OpenAPI +### Генерация TypeScript-клиента с предобработанным OpenAPI -Теперь, так как конечный результат находится в файле `openapi.json`, вы можете изменить `package.json`, чтобы использовать этот локальный файл, например: +Теперь, так как конечный результат находится в файле `openapi.json`, вы измените файл `package.json`, чтобы использовать этот локальный файл, например: ```JSON hl_lines="7" { @@ -240,22 +240,22 @@ FastAPI использует **уникальный идентификатор** } ``` -После генерации нового клиента вы теперь получите **чистые имена методов**, с всеми **автодополнениями**, **встроенными ошибками** и прочим: +После генерации нового клиента у вас теперь будут **чистые названия методов**, с всеми **подсказками автозавершения**, **ошибками на лету** и т.д.: ## Преимущества -При использовании автоматически сгенерированных клиентов вы получите **автодополнение** для: +При использовании автоматически сгенерированных клиентов вы получите **автозавершение** для: * Методов. -* Загружаемых данных в теле запроса, параметрах запроса и т. д. -* Полей в ответах. +* Полезной нагрузки запроса в теле, параметрах запроса и т.д. +* Полезной нагрузки ответа. -Вы также получите **встроенные ошибки** для всего. +Вы также получите **ошибки на лету** для всего. -И всякий раз, когда вы обновляете код серверной части и **перегенерируете** фронтенд, он будет иметь все новые *операции пути* как методы, старые будут удалены, и любые другие изменения будут отражены в сгенерированном коде. 🤓 +И всякий раз, когда вы обновляете код на серверной стороне и **регенерируете** фронтенд, он будет содержать любые новые *операции пути* как методы, старые будут удалены, а любые другие изменения будут отражены в сгенерированном коде. 🤓 -Это также значит, что если что-то изменилось, это будет **отражено** в клиентском коде автоматически. И если вы **соберёте** клиента, вы получите ошибку, если данные не совпадают. +Это также означает, что если что-то изменится, это будет **отражено** в клиентском коде автоматически. И если вы **соберёте** клиент, у него возникнет ошибка, если у вас возникнет **несоответствие** в используемых данных. -Таким образом, вы сможете **обнаружить многие ошибки** на ранней стадии цикла разработки, вместо того чтобы ждать, пока ошибки проявятся у ваших конечных пользователей в производстве, и затем пытаться выяснить, где находится проблема. ✨ +Таким образом, вы **обнаружите множество ошибок** на раннем этапе цикла разработки, вместо того чтобы ждать, пока ошибки проявятся у ваших конечных пользователей в продакшне, и потом пытаться выяснить, в чем проблема. ✨ diff --git a/docs/ru/docs/advanced/middleware.md b/docs/ru/docs/advanced/middleware.md index b80e92bb5..e2f1a8ba1 100644 --- a/docs/ru/docs/advanced/middleware.md +++ b/docs/ru/docs/advanced/middleware.md @@ -1,20 +1,20 @@ -# Продвинутые Middleware +# Продвинутое использование Middleware -В основном учебнике вы прочитали, как добавить [Custom Middleware](../tutorial/middleware.md){.internal-link target=_blank} в ваше приложение. +В основном руководстве вы узнали, как добавить [пользовательский Middleware](../tutorial/middleware.md){.internal-link target=_blank} в ваше приложение. -Также вы узнали, как обрабатывать [CORS с помощью `CORSMiddleware`](../tutorial/cors.md){.internal-link target=_blank}. +А также вы узнали, как обрабатывать [CORS с использованием `CORSMiddleware`](../tutorial/cors.md){.internal-link target=_blank}. -В этой секции мы рассмотрим, как использовать другие middlewares. +В этом разделе мы увидим, как использовать другие middleware. -## Добавление ASGI middlewares +## Добавление ASGI middleware -Так как **FastAPI** основан на Starlette и реализует спецификацию ASGI, вы можете использовать любое ASGI middleware. +Так как **FastAPI** основан на Starlette и реализует спецификацию ASGI, вы можете использовать любой ASGI middleware. -Middleware не обязательно должен быть создан для FastAPI или Starlette, чтобы работать, до тех пор, пока он следует спецификации ASGI. +Для работы middleware не обязательно должны быть созданы специально для FastAPI или Starlette, достаточно того, чтобы они следовали спецификации ASGI. -В общем, ASGI middlewares - это классы, которые ожидают получить ASGI приложение в качестве первого аргумента. +В общем случае, ASGI middleware представляют собой классы, которые ожидают получение ASGI приложения в качестве первого аргумента. -Таким образом, в документации для сторонних ASGI middlewares вероятно, вас попросят сделать что-то похожее на: +Таким образом, в документации для сторонних ASGI middleware, скорее всего, будет указано сделать следующее: ```Python from unicorn import UnicornMiddleware @@ -24,7 +24,7 @@ app = SomeASGIApp() new_app = UnicornMiddleware(app, some_config="rainbow") ``` -Но FastAPI (на самом деле Starlette) предоставляет более простой способ сделать это, который гарантирует, что внутренние middleware будут правильно обрабатывать ошибки сервера и пользовательские обработчики исключений. +Но FastAPI (на самом деле Starlette) предоставляет более простой способ сделать это, обеспечивая правильную обработку ошибок сервера и работу пользовательских обработчиков ошибок. Для этого используйте `app.add_middleware()` (как в примере для CORS). @@ -37,60 +37,60 @@ app = FastAPI() app.add_middleware(UnicornMiddleware, some_config="rainbow") ``` -`app.add_middleware()` принимает класс middleware в качестве первого аргумента и любые дополнительные аргументы, которые будут переданы в middleware. +`app.add_middleware()` принимает класс middleware в качестве первого аргумента и любые дополнительные аргументы, которые должны быть переданы в middleware. -## Встроенные middlewares +## Интегрированные middleware -**FastAPI** включает несколько middlewares для общих случаев использования, дальше мы рассмотрим как их использовать. +**FastAPI** включает несколько middleware для общих случаев использования, далее мы рассмотрим, как их использовать. /// note | Технические детали -Для следующих примеров вы также могли бы использовать `from starlette.middleware.something import SomethingMiddleware`. +В следующих примерах вы также можете использовать `from starlette.middleware.something import SomethingMiddleware`. -**FastAPI** предоставляет несколько middlewares в `fastapi.middleware` просто для вашего удобства, как разработчика. Но большинство доступных middlewares приходят непосредственно из Starlette. +**FastAPI** предоставляет несколько middleware в `fastapi.middleware` исключительно для удобства разработчика. Но большинство доступных middleware поступает непосредственно из Starlette. /// ## `HTTPSRedirectMiddleware` -Обеспечивает, чтобы все входящие запросы были либо `https`, либо `wss`. +Обеспечивает, чтобы все входящие запросы были перенаправлены на `https` или `wss`. -Любой входящий запрос на `http` или `ws` будет перенаправлен на защищённую схему. +Любой входящий запрос на `http` или `ws` будет перенаправлен на защищенную схему. {* ../../docs_src/advanced_middleware/tutorial001.py hl[2,6] *} ## `TrustedHostMiddleware` -Обеспечивает, чтобы все входящие запросы имели правильно установленный заголовок `Host`, чтобы защититься от атак посредством подмены заголовка HTTP Host. +Обеспечивает наличие корректно заданного HTTP-заголовка `Host` во всех входящих запросах для защиты от атак на основе HTTP-заголовка Host. {* ../../docs_src/advanced_middleware/tutorial002.py hl[2,6:8] *} Поддерживаются следующие аргументы: -* `allowed_hosts` - Список доменных имён, которые должны быть разрешены в качестве имён хоста. Поддерживаются подстановочные домены, такие как `*.example.com`, для совпадения с поддоменами. Чтобы разрешить любое имя хоста, либо используйте `allowed_hosts=["*"]`, либо пропустите middleware. +* `allowed_hosts` - список доменных имен, которые разрешены в качестве имен хостов. Разрешены шаблоны доменов, такие как `*.example.com`, для соответствия поддоменам. Для разрешения всех имен хостов можно использовать `allowed_hosts=["*"]` или вовсе не добавлять middleware. -Если входящий запрос проходит проверку неправильно, то будет отправлен ответ `400`. +Если входящий запрос не валидируется, отправляется ответ с кодом `400`. ## `GZipMiddleware` -Обрабатывает GZip ответы для любого запроса, который включает `"gzip"` в заголовке `Accept-Encoding`. +Обрабатывает GZip-ответы для любого запроса, который включает `"gzip"` в HTTP-заголовке `Accept-Encoding`. -Middleware обрабатывает как стандартные, так и потоковые ответы. +Middleware будет обрабатывать как стандартные, так и потоковые HTTP-ответы. {* ../../docs_src/advanced_middleware/tutorial003.py hl[2,6] *} Поддерживаются следующие аргументы: -* `minimum_size` - Не использовать GZip для ответов, размер которых меньше этого минимума в байтах. По умолчанию `500`. -* `compresslevel` - Используется во время GZip сжатия. Это целое число в диапазоне от 1 до 9. Значение по умолчанию `9`. Меньшее значение приводит к более быстрому сжатию, но большим размерам файлов, в то время как большее значение приводит к более медленному сжатию, но меньшим размерам файлов. +* `minimum_size` - не выполнять GZip сжатие для HTTP-ответов, которые меньше этого минимального размера в байтах. По умолчанию `500`. +* `compresslevel` - используется во время GZip сжатия. Это число в диапазоне от 1 до 9. По умолчанию `9`. Меньшее значение приводит к более быстрому сжатию, но большему размеру файлов, в то время как большее значение приводит к более медленному сжатию, но меньшему размеру файлов. -## Другие middlewares +## Другие middleware -Существует много других ASGI middlewares. +Существует много других ASGI middleware. Например: -* Uvicorn's `ProxyHeadersMiddleware` +* `ProxyHeadersMiddleware` от Uvicorn * MessagePack -Чтобы увидеть другие доступные middlewares, ознакомьтесь с документацией по Middlewares от Starlette и ASGI Awesome List. +Чтобы увидеть другие доступные middleware, ознакомьтесь с документацией Starlette по Middleware и списком ASGI Awesome List. diff --git a/docs/ru/docs/advanced/openapi-callbacks.md b/docs/ru/docs/advanced/openapi-callbacks.md index 05a50a3f0..3de7f3610 100644 --- a/docs/ru/docs/advanced/openapi-callbacks.md +++ b/docs/ru/docs/advanced/openapi-callbacks.md @@ -1,124 +1,124 @@ # OpenAPI Callbacks -Вы можете создать API с *операцией пути*, которая может инициировать запрос к *внешнему API*, созданному кем-то другим (возможно, тем же разработчиком, который будет *использовать* ваше API). +Вы можете создать API с *операцией пути*, которая может инициировать запрос к *внешнему API*, созданному кем-то другим (вероятно, тем же разработчиком, который будет *использовать* ваше API). -Процесс, который происходит, когда ваше API-приложение вызывает *внешний API*, называется "обратным вызовом" (callback). Потому что программа, написанная внешним разработчиком, отправляет запрос в ваше API, а затем ваше API делает "обратный вызов", отправляя запрос во *внешний API* (который, вероятно, был создан тем же разработчиком). +Процесс, который происходит, когда ваше API-приложение вызывает *внешний API*, называется "callback". Потому что ПО, написанное внешним разработчиком, отправляет запрос вашему API, а затем ваше API *отвечает*, отправляя запрос к *внешнему API* (который, возможно, был создан тем же разработчиком). -В этом случае вам может понадобиться документировать, как этот внешний API *должен* выглядеть. Какие *операции пути* он должен иметь, какое тело ожидать, какой ответ должен возвращать и т. д. +В этом случае, вы могли бы захотеть задокументировать, как этот внешний API *должен* выглядеть. Какие *операции пути* он должен содержать, какое тело ожидать, какой ответ должен возвращать и т.д. -## Приложение с обратными вызовами +## Приложение с callback'ами -Давайте посмотрим на всё это на примере. +Рассмотрим это на примере. -Представьте, что вы разрабатываете приложение, которое позволяет создавать счета-фактуры. +Представьте, что вы разрабатываете приложение, позволяющее создавать счета. -Эти счета-фактуры будут иметь `id`, `title` (необязательно), `customer` и `total`. +Эти счета будут иметь `id`, `title` (опционально), `customer` и `total`. -Пользователь вашего API (внешний разработчик) создаст счет-фактуру в вашем API с помощью POST-запроса. +Пользователь вашего API (внешний разработчик) создаст счет в вашем API с помощью POST-запроса. -Затем ваше API (давайте представим): +Затем ваше API будет (давайте представим): -* Отправит счет некоторому клиенту внешнего разработчика. -* Соберет деньги. -* Отправит уведомление обратно пользователю API (внешнему разработчику). - * Это будет сделано путем отправки POST-запроса (из *вашего API*) на какой-то *внешний API*, предоставленный тем внешним разработчиком (это и есть "обратный вызов"). +* Отправлять счет какому-то клиенту внешнего разработчика. +* Собирать деньги. +* Отправлять уведомление обратно пользователю API (внешнему разработчику). + * Это будет сделано с помощью отправки POST-запроса (от *вашего API*) в некоторый *внешний API*, предоставленный этим внешним разработчиком (это и есть "callback"). ## Обычное приложение **FastAPI** -Давайте сначала посмотрим, как будет выглядеть обычное API-приложение до добавления обратного вызова. +Сначала посмотрим, как обычное приложение API выглядело бы до добавления callback'а. -Оно будет иметь *операцию пути*, которая будет получать тело `Invoice`, и параметр запроса `callback_url`, который будет содержать URL для обратного вызова. +Оно будет иметь *операцию пути*, которая будет принимать `Invoice` в теле запроса и параметр запроса `callback_url`, который будет содержать URL для callback'а. -Эта часть довольно обычная, большая часть кода, вероятно, уже знакома вам: +Эта часть довольно обычная, и, вероятно, большая часть кода уже знакома вам: {* ../../docs_src/openapi_callbacks/tutorial001.py hl[9:13,36:53] *} -/// tip | Совет +/// tip | Подсказка -Параметр запроса `callback_url` использует тип Pydantic Url. +Параметр запроса `callback_url` использует тип Url из Pydantic Url. /// -Единственное, что ново, это `callbacks=invoices_callback_router.routes` в качестве аргумента для декоратора *операции пути*. Мы посмотрим, что это такое дальше. +Единственное новое здесь — это `callbacks=invoices_callback_router.routes` как аргумент к *декоратору операции пути*. Дальше мы увидим, что это значит. -## Документирование обратного вызова +## Документирование callback'а -Фактический код обратного вызова будет сильно зависеть от вашего собственного API-приложения. +Фактический код callback'а будет сильно зависеть от вашего API-приложения. -И, вероятно, будет значительно отличаться для разных приложений. +И, вероятно, значительно изменится от одного приложения к другому. -Это может быть всего одна или две строчки кода, например: +Это может быть всего одна или две строчки кода, такие как: ```Python callback_url = "https://example.com/api/v1/invoices/events/" httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) ``` -Но, возможно, самая важная часть обратного вызова — это убедиться, что пользователь вашего API (внешний разработчик) корректно реализует *внешний API*, в соответствии с данными, которые *ваше API* собирается отправить в теле запроса для обратного вызова и т. д. +Но, возможно, наиболее важная часть callback'а — это убедиться, что пользователь вашего API (внешний разработчик) корректно реализует *внешний API*, согласно данным, которые *ваше API* собирается отправить в теле запроса callback'а и т.д. -Таким образом, что мы собираемся сделать дальше, это добавить код для документирования того, как этот *внешний API* должен выглядеть, чтобы принимать обратный вызов от *вашего API*. +Итак, следующее, что мы сделаем, это добавим код для документации, как этот *внешний API* должен выглядеть для получения callback'а от *вашего API*. -Эта документация будет отображаться в Swagger UI по адресу `/docs` в вашем API и она позволит внешним разработчикам знать, как построить *внешний API*. +Эта документация отобразится в интерфейсе Swagger по адресу `/docs` в вашем API и позволит внешним разработчикам узнать, как создать *внешний API*. -Этот пример не реализует сам обратный вызов (это может быть всего одна строка кода), только часть документации. +Этот пример не реализует сам callback (это может быть всего одна строка кода), только часть документации. -/// tip | Совет +/// tip | Подсказка -Фактический обратный вызов — это просто HTTP-запрос. +Фактический callback — это просто HTTP-запрос. -При самостоятельной реализации обратного вызова вы можете использовать что-то вроде HTTPX или Requests. +При реализации callback'а самостоятельно, вы можете использовать что-то вроде HTTPX или Requests. /// -## Написание кода документации для обратного вызова +## Написание кода документации для callback'а -Этот код не будет выполняться в вашем приложении, нам он нужен только для того, чтобы *документировать*, как этот *внешний API* должен выглядеть. +Этот код не будет выполнен в вашем приложении, нам нужно его только чтобы *документировать*, как *внешний API* должен выглядеть. -Но вы уже знаете, как легко создать автоматическую документацию для API с использованием **FastAPI**. +Но вы уже знаете, как легко создавать автоматическую документацию для API с **FastAPI**. -Итак, мы собираемся использовать эти знания, чтобы задокументировать, как *внешний API* должен выглядеть... создав *операции пути*, которые внешний API должен реализовать (те, которые ваше API будет вызывать). +Поэтому мы используем эти же знания, чтобы задокументировать, как *внешний API* должен выглядеть... создавая *операцию(ии) пути*, которые внешний API должен реализовать (те, которые ваше API вызовет). -/// tip | Совет +/// tip | Подсказка -При написании кода для документирования обратного вызова может быть полезно представить, что вы — это тот *внешний разработчик*. И что вы в данный момент реализуете *внешний API*, а не *ваше API*. +Когда пишете код для документации callback'а, может быть полезно представить, что вы — этот *внешний разработчик*. И что вы в данный момент реализуете *внешний API*, а не *ваше API*. -Временное принятие этой точки зрения (внешнего разработчика) может помочь вам почувствовать, что более очевидно, где разместить параметры, модель Pydantic для тела, для ответа и т. д. для этого *внешнего API*. +Временное принятие этой точки зрения (внешнего разработчика) поможет вам скорее определить, куда помещать параметры, Pydantic-модель для тела запроса, для ответа и т.д. для этого *внешнего API*. /// -### Создание `APIRouter` для обратного вызова +### Создание callback `APIRouter` -Сначала создайте новый `APIRouter`, который будет содержать один или несколько обратных вызовов. +Сначала создайте новый `APIRouter`, который будет содержать один или несколько callback'ов. {* ../../docs_src/openapi_callbacks/tutorial001.py hl[3,25] *} -### Создание *операции пути* для обратного вызова +### Создание callback *операции пути* -Чтобы создать *операцию пути* для обратного вызова, используйте тот же `APIRouter`, который вы создали выше. +Чтобы создать callback *операцию пути*, используйте тот же `APIRouter`, который вы создали выше. -Это должно выглядеть так же, как обычная *операция пути* в FastAPI: +Она должна выглядеть как обычная операция пути FastAPI: -* Вероятно, должно быть объявлено тело, которое она должна получить, например, `body: InvoiceEvent`. -* Также может быть объявлена модель ответа, которую она должна возвращать, например, `response_model=InvoiceEventReceived`. +* Она, вероятно, должна иметь объявление тела запроса, которое она должна принять, например `body: InvoiceEvent`. +* И она может также иметь объявление ответа, который она должна вернуть, например `response_model=InvoiceEventReceived`. {* ../../docs_src/openapi_callbacks/tutorial001.py hl[16:18,21:22,28:32] *} -Существует 2 основных отличия от обычной *операции пути*: +Есть 2 основных отличия от обычной *операции пути*: -* Она не должна содержать никакого реального кода, потому что ваше приложение никогда не будет вызывать этот код. Он используется только для документирования *внешнего API*. Поэтому функция может просто содержать `pass`. -* *Путь* может содержать выражение OpenAPI 3 (см. ниже), где могут использоваться переменные с параметрами и частями исходного запроса, отправленного в *ваше API*. +* Реальный код не нужен, так как ваше приложение никогда не вызовет этот код. Он используется только для документирования *внешнего API*. Поэтому функция может просто содержать `pass`. +* В *пути* может содержаться выражение OpenAPI 3 (подробнее ниже), где можно использовать переменные с параметрами и частями оригинального запроса, отправленного к *вашему API*. -### Выражение пути обратного вызова +### Выражение пути callback'а -*Путь* обратного вызова может содержать выражение OpenAPI 3, которое может содержать части исходного запроса, отправленного в *ваше API*. +Путь callback'а может содержать выражение OpenAPI 3, которое может включать части оригинального запроса, отправленного к *вашему API*. -В данном случае это `str`: +В этом случае это `str`: ```Python "{$callback_url}/invoices/{$request.body.id}" ``` -Таким образом, если пользователь вашего API (внешний разработчик) отправляет запрос в *ваше API* на: +Таким образом, если пользователь вашего API (внешний разработчик) отправляет запрос к *вашему API* по адресу: ``` https://yourapi.com/invoices/?callback_url=https://www.external.org/events @@ -134,7 +134,7 @@ https://yourapi.com/invoices/?callback_url=https://www.external.org/events } ``` -тогда *ваше API* обработает счет, и в какой-то момент позже отправит запрос для обратного вызова на `callback_url` (во *внешний API*): +тогда *ваше API* обработает счет, и чуть позже отправит callback-запрос на `callback_url` (во *внешний API*): ``` https://www.external.org/events/invoices/2expen51ve @@ -149,7 +149,7 @@ https://www.external.org/events/invoices/2expen51ve } ``` -и оно будет ожидать ответ от этого *внешнего API* с JSON-телом как: +и ожидает ответа от этого *внешнего API* с JSON-телом вроде: ```JSON { @@ -157,29 +157,29 @@ https://www.external.org/events/invoices/2expen51ve } ``` -/// tip | Совет +/// tip | Подсказка -Обратите внимание, как URL для обратного вызова содержит URL, полученный в виде параметра запроса в `callback_url` (`https://www.external.org/events`) и также `id` счета-фактуры из JSON-тела (`2expen51ve`). +Обратите внимание, как callback URL включает URL, полученный как параметр запроса в `callback_url` (`https://www.external.org/events`), и также `id` счета из тела JSON (`2expen51ve`). /// -### Добавление маршрутизатора для обратных вызовов +### Добавление router для callback'ов -На этом этапе у вас есть нужные *операции пути для обратных вызовов* (те, которые *внешний разработчик* должен реализовать во *внешнем API*) в созданном выше маршрутизаторе для обратных вызовов. +На данном этапе у вас есть *операция(ии) пути для callback'а*, необходимые (те, которые *внешний разработчик* должен реализовать во *внешнем API*) в callback router, который вы создали выше. -Теперь используйте параметр `callbacks` в *декораторе операции пути вашего API*, чтобы передать атрибут `.routes` (на самом деле это просто `list` маршрутов/*операций путей*) из этого маршрутизатора для обратных вызовов: +Теперь используйте параметр `callbacks` в *декораторе операции пути вашего API*, чтобы передать атрибут `.routes` (который на самом деле является просто `list`'ом маршрутов/*операций пути*) из этого callback router: {* ../../docs_src/openapi_callbacks/tutorial001.py hl[35] *} -/// tip | Совет +/// tip | Подсказка -Обратите внимание, что вы передаете не сам маршрутизатор (`invoices_callback_router`) в `callback=`, а атрибут `.routes`, как в `invoices_callback_router.routes`. +Обратите внимание, что вы не передаете сам router (`invoices_callback_router`) в `callback=`, а передаете атрибут `.routes`, как в `invoices_callback_router.routes`. /// ### Проверка документации -Теперь вы можете запустить своё приложение и перейти на http://127.0.0.1:8000/docs. +Теперь вы можете запустить ваше приложение и перейти на http://127.0.0.1:8000/docs. Вы увидите вашу документацию, включая раздел "Callbacks" для вашей *операции пути*, который показывает, как должен выглядеть *внешний API*: diff --git a/docs/ru/docs/advanced/openapi-webhooks.md b/docs/ru/docs/advanced/openapi-webhooks.md index ba7048fa8..4854bd513 100644 --- a/docs/ru/docs/advanced/openapi-webhooks.md +++ b/docs/ru/docs/advanced/openapi-webhooks.md @@ -1,55 +1,55 @@ -# OpenAPI Вебхуки +# OpenAPI Webhooks -Существуют случаи, когда вы хотите сообщить вашим **пользователям API**, что ваше приложение может вызвать *их* приложение (отправив запрос) с некоторыми данными, обычно чтобы **уведомить** о каком-то типе **события**. +Существуют случаи, когда вы хотите сообщить пользователям вашего API, что ваше приложение может отправлять запросы их приложениям с данными, обычно для уведомления о каком-то событии. -Это означает, что вместо обычного процесса, когда ваши пользователи отправляют запросы вашему API, это **ваш API** (или ваше приложение), который может **отправлять запросы их системе** (их API, их приложению). +Это означает, что вместо обычного процесса, когда ваши пользователи отправляют запросы вашему API, это ваш API (или ваше приложение) может отправлять запросы их системе (их API, их приложению). -Обычно это называется **вебхук**. +Это обычно называется **webhook**. ## Шаги вебхуков -Процесс обычно заключается в том, что **вы определяете** в своем коде, какое сообщение вы будете отправлять, **тело запроса**. +Процесс обычно состоит в том, что **вы определяете** в вашем коде сообщение, которое вы собираетесь отправить, **тело запроса**. -Вы также каким-то образом определяете, в какие **моменты** ваше приложение будет отправлять эти запросы или события. +Вы также каким-либо образом определяете, в какие **моменты** ваше приложение будет отправлять эти запросы или события. -А **ваши пользователи** каким-то образом (например, в веб-интерфейсе где-то) определяют **URL**, на который ваше приложение должно отправлять эти запросы. +И **ваши пользователи** каким-либо образом (например, в веб-панели управления) определяют **URL**, куда ваше приложение должно отправлять эти запросы. -Вся **логика** относительно того, как регистрировать URL для вебхуков и писать код для отправки этих запросов, зависит от вас. Вы пишете это так, как хотите, в **вашем собственном коде**. +Вся **логика** регистрации URL-адресов для вебхуков и кода для фактической отправки этих запросов зависит от вас. Вы пишете это в **собственном коде** так, как хотите. -## Документирование вебхуков с **FastAPI** и OpenAPI +## Документирование вебхуков с помощью **FastAPI** и OpenAPI -С помощью **FastAPI**, используя OpenAPI, вы можете определить имена этих вебхуков, типы HTTP операций, которые ваше приложение может отправлять (например, `POST`, `PUT` и т.д.), и тела **запросов**, которые ваше приложение будет отправлять. +С помощью **FastAPI** и OpenAPI вы можете определить названия этих вебхуков, типы HTTP операций, которые ваше приложение может отправлять (например, `POST`, `PUT` и т.д.), и **тела запросов**, которые ваше приложение будет отправлять. -Это может значительно облегчить вашим пользователям **реализацию их API** для приема ваших **вебхуков**, они даже могут автоматически сгенерировать часть своего собственного кода API. +Это может значительно упростить вашим пользователям **внедрение их API** для получения ваших **вебхуков**, они даже могут автоматически сгенерировать часть своего API кода. /// info | Информация -Вебхуки доступны в OpenAPI 3.1.0 и выше, поддерживаются FastAPI `0.99.0` и выше. +Вебхуки доступны в OpenAPI 3.1.0 и выше, поддерживаемые FastAPI `0.99.0` и выше. /// ## Приложение с вебхуками -Когда вы создаете приложение **FastAPI**, существует атрибут `webhooks`, который вы можете использовать для определения *вебхуков*, так же, как вы определяете *операции с путями*, например, с помощью `@app.webhooks.post()`. +Когда вы создаете приложение **FastAPI**, есть атрибут `webhooks`, который вы можете использовать для определения *вебхуков* так же, как вы бы определяли *операции пути*, например с помощью `@app.webhooks.post()`. {* ../../docs_src/openapi_webhooks/tutorial001.py hl[9:13,36:53] *} -Вебхуки, которые вы определите, окажутся в **OpenAPI** схеме и в автоматическом **документированном интерфейсе**. +Вебхуки, которые вы определяете, попадут в **схему OpenAPI** и в **автоматическую документацию UI**. /// info | Информация -Объект `app.webhooks` на самом деле просто `APIRouter`, тот же тип, который вы бы использовали при структурировании вашего приложения с несколькими файлами. +Объект `app.webhooks` на самом деле является `APIRouter`, того же типа, который вы бы использовали при структурировании своего приложения с множеством файлов. /// -Обратите внимание, что с вебхуками вы на самом деле не объявляете *путь* (как `/items/`), текст, который вы передаете, является просто **идентификатором** вебхука (именем события), например, в `@app.webhooks.post("new-subscription")` имя вебхука - `new-subscription`. +Обратите внимание, что с вебхуками вы на самом деле не объявляете *путь* (например, `/items/`), текст, который вы передаете, является просто **идентификатором** вебхука (название события), например в `@app.webhooks.post("new-subscription")`, имя вебхука — `new-subscription`. -Это потому, что предполагается, что **ваши пользователи** будут определять фактический **путь URL**, куда они хотят получать запрос вебхука другим способом (например, через веб-интерфейс). +Это потому, что ожидается, что **ваши пользователи** определят фактический **путь URL**, куда они хотят получать запрос webhook, каким-то другим образом (например, в веб-панели управления). ### Проверьте документацию -Теперь вы можете запустить ваше приложение и перейти по ссылке http://127.0.0.1:8000/docs. +Теперь вы можете запустить ваше приложение и перейти по адресу http://127.0.0.1:8000/docs. -Вы увидите, что в вашей документации есть обычные *операции пути*, а теперь и некоторые **вебхуки**: +Вы увидите, что ваша документация содержит обычные *операции пути* и теперь также некоторые **вебхуки**: diff --git a/docs/ru/docs/advanced/path-operation-advanced-configuration.md b/docs/ru/docs/advanced/path-operation-advanced-configuration.md index 55000f728..057d14952 100644 --- a/docs/ru/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/ru/docs/advanced/path-operation-advanced-configuration.md @@ -1,36 +1,36 @@ -# Расширенная конфигурация операций пути +# Продвинутая конфигурация операций пути ## OpenAPI operationId /// warning | Предупреждение -Если вы не "эксперт" в OpenAPI, вам, вероятно, это не нужно. +Если вы не "эксперт" в OpenAPI, то, скорее всего, вам это не понадобится. /// -Вы можете установить OpenAPI `operationId` для использования в вашей *операции пути* с параметром `operation_id`. +Вы можете задать `operationId` для OpenAPI, который будет использоваться в вашей *операции пути* с помощью параметра `operation_id`. -Вам нужно будет убедиться, что он уникален для каждой операции. +Следует удостовериться, что он уникален для каждой операции. {* ../../docs_src/path_operation_advanced_configuration/tutorial001.py hl[6] *} -### Использование имени функции *операции пути* как operationId +### Использование имени функции *операции пути* в качестве operationId -Если вы хотите использовать имена функций своих API в качестве `operationId`, вы можете перебрать все из них и переопределить каждый `operation_id` для их *операций пути* используя `APIRoute.name`. +Если вы хотите использовать имена ваших функций API в качестве `operationId`, вы можете перебрать их все и переопределить `operation_id` каждой *операции пути*, используя `APIRoute.name`. -Вы должны сделать это после добавления всех своих *операций пути*. +Необходимо сделать это после добавления всех ваших *операций пути*. {* ../../docs_src/path_operation_advanced_configuration/tutorial002.py hl[2, 12:21, 24] *} /// tip | Совет -Если вы вручную вызываете `app.openapi()`, вам следует обновить `operationId` перед этим. +Если вы вручную вызываете `app.openapi()`, обновите `operationId` до этого. /// /// warning | Предупреждение -Если вы так делаете, вам нужно убедиться, что каждая из ваших *функций операций пути* имеет уникальное имя. +Если вы это делаете, необходимо удостовериться, что каждая из ваших *функций операций пути* имеет уникальное имя. Даже если они находятся в разных модулях (файлах Python). @@ -38,51 +38,51 @@ ## Исключение из OpenAPI -Чтобы исключить *операцию пути* из создаваемой схемы OpenAPI (и, следовательно, из систем автоматической документации), используйте параметр `include_in_schema` и установите его в `False`: +Чтобы исключить *операцию пути* из генерируемой схемы OpenAPI (и таким образом, из систем автоматической документации), используйте параметр `include_in_schema` и установите его значение как `False`: {* ../../docs_src/path_operation_advanced_configuration/tutorial003.py hl[6] *} -## Расширенное описание из docstring +## Расширенное описание из строки документации -Вы можете ограничить строки, используемые из docstring функции *операции пути* для OpenAPI. +Вы можете ограничить количество строк, используемых из строки документации функции *операции пути* для OpenAPI. -Добавление `\f` (экранированный символ "form feed") приводит к тому, что **FastAPI** обрезает вывод, используемый для OpenAPI в этой точке. +Добавление `\f` (экранированный символ "перевод страницы") приведет к тому, что **FastAPI** обрежет вывод, используемый для OpenAPI, на этом месте. -Это не будет отображаться в документации, но другие инструменты (такие как Sphinx) смогут использовать остальное. +Этот символ не покажется в документации, но другие инструменты (такие как Sphinx) смогут использовать остальную часть. {* ../../docs_src/path_operation_advanced_configuration/tutorial004.py hl[19:29] *} ## Дополнительные ответы -Вы, вероятно, уже видели, как объявлять `response_model` и `status_code` для *операции пути*. +Вы, вероятно, уже знаете, как объявить `response_model` и `status_code` для *операции пути*. -Это определяет метаданные о основном ответе *операции пути*. +Это определяет метаданные об основном ответе *операции пути*. -Вы также можете объявить дополнительные ответы с их моделями, статусами кодов и т. д. +Вы также можете объявить дополнительные ответы с их моделями, статус-кодами и т.д. -Здесь есть целая глава в документации об этом, вы можете прочитать ее в разделе [Дополнительные ответы в OpenAPI](additional-responses.md){.internal-link target=_blank}. +В документации есть целая глава об этом, которую вы можете прочитать в разделе [Дополнительные ответы в OpenAPI](additional-responses.md){.internal-link target=_blank}. -## OpenAPI Extra +## Дополнения OpenAPI -Когда вы объявляете *операцию пути* в своем приложении, **FastAPI** автоматически генерирует соответствующие метаданные об этой *операции пути* для включения в схему OpenAPI. +Когда вы объявляете *операцию пути* в вашем приложении, **FastAPI** автоматически генерирует соответствующие метаданные об этой *операции пути*, чтобы включить их в схему OpenAPI. /// note | Технические детали -В спецификации OpenAPI это называется Operation Object. +В спецификации OpenAPI это называется Объект операции. /// -Он содержит всю информацию о *операции пути* и используется для генерации автоматической документации. +Это содержит всю информацию о *операции пути* и используется для генерации автоматической документации. -Он включает `tags`, `parameters`, `requestBody`, `responses` и т. д. +Это включает в себя `tags`, `parameters`, `requestBody`, `responses` и т.д. -Эта OpenAPI схема, специфичная для *операции пути*, обычно генерируется автоматически **FastAPI**, но вы также можете расширить ее. +Эта схема OpenAPI для данной *операции пути* обычно генерируется автоматически **FastAPI**, но ее можно и расширить. /// tip | Совет -Это низкоуровневая точка расширения. +Это точка низкоуровневого расширения. -Если вам нужно только объявить дополнительные ответы, более удобный способ сделать это — с [Дополнительные ответы в OpenAPI](additional-responses.md){.internal-link target=_blank}. +Если вам нужно только объявить дополнительные ответы, более удобный способ сделать это — через [Дополнительные ответы в OpenAPI](additional-responses.md){.internal-link target=_blank}. /// @@ -90,15 +90,15 @@ ### Расширения OpenAPI -Этот `openapi_extra` может быть полезен, например, для объявления [OpenAPI Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions): +Этот `openapi_extra` может быть полезен, например, чтобы объявить [Расширения OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions): {* ../../docs_src/path_operation_advanced_configuration/tutorial005.py hl[6] *} -Если вы откроете автоматическую документацию API, ваше расширение будет отображено внизу конкретной *операции пути*. +Если вы откроете автоматическую документацию API, ваше расширение появится внизу конкретной *операции пути*. -И если вы посмотрите на результат OpenAPI (по адресу `/openapi.json` в вашем API), вы увидите свое расширение как часть конкретной *операции пути* тоже: +И если вы увидите результат OpenAPI (по адресу `/openapi.json` в вашем API), вы увидите ваше расширение также как часть конкретной *операции пути*: ```JSON hl_lines="22" { @@ -129,29 +129,29 @@ } ``` -### Индивидуальная OpenAPI схема *операции пути* +### Пользовательская схема OpenAPI *операции пути* Словарь в `openapi_extra` будет глубоко объединен с автоматически сгенерированной схемой OpenAPI для *операции пути*. -Таким образом, вы сможете добавить дополнительные данные к автоматически сгенерированной схеме. +Так вы можете добавить дополнительные данные в автоматически сгенерированную схему. -Например, вы могли бы решить считать и проверять запрос с помощью вашего собственного кода, не используя автоматические функции FastAPI с Pydantic, но при этом вы могли бы захотеть определить запрос в схеме OpenAPI. +Например, вы можете решить сами считывать и валидировать запрос без использования автоматических функций FastAPI с Pydantic, но вы все равно можете захотеть определить запрос в схеме OpenAPI. -Вы могли бы сделать это с помощью `openapi_extra`: +Вы можете сделать это с помощью `openapi_extra`: {* ../../docs_src/path_operation_advanced_configuration/tutorial006.py hl[19:36, 39:40] *} -В этом примере мы не объявляли модель Pydantic. Фактически, тело запроса даже не проанализировано как JSON, оно читается напрямую как `bytes`, и функция `magic_data_reader()` будет отвечать за его парсинг каким-то образом. +В этом примере мы не объявили никакой Pydantic-модели. На самом деле тело запроса даже не проанализировано как JSON, оно считывается напрямую как `bytes`, и функция `magic_data_reader()` будет отвечать за его парсинг. Тем не менее, мы можем объявить ожидаемую схему для тела запроса. -### Индивидуальный тип содержимого OpenAPI +### Пользовательский тип содержимого OpenAPI -Используя эту же хитрость, вы могли бы использовать модель Pydantic для определения JSON Schema, которое затем включается в пользовательскую секцию OpenAPI схемы для *операции пути*. +Используя этот же трюк, вы можете использовать Pydantic-модель для определения JSON-схемы, которая затем будет включена в пользовательский раздел схемы OpenAPI для *операции пути*. -И вы могли бы сделать это, даже если тип данных в запросе не является JSON. +И вы можете сделать это даже если тип данных в запросе не JSON. -Например, в этом приложении мы не используем интегрированную функциональность FastAPI для извлечения JSON Schema из моделей Pydantic, ни автоматической валидации для JSON. Фактически, мы объявляем тип содержимого запроса как YAML, а не JSON: +Например, в этом приложении мы не используем интегрированные функции FastAPI для извлечения JSON-схемы из Pydantic-моделей и автоматической валидации для JSON. В самом деле, мы объявляем тип содержимого запроса как YAML, а не JSON: //// tab | Pydantic v2 @@ -167,15 +167,15 @@ /// info | Информация -В версии Pydantic 1 метод для получения JSON Schema для модели назывался `Item.schema()`, в версии Pydantic 2 этот метод называется `Item.model_json_schema()`. +В версии Pydantic 1 метод для получения JSON-схемы для модели назывался `Item.schema()`, в версии Pydantic 2 метод называется `Item.model_json_schema()`. /// -Тем не менее, хотя мы и не используем стандартную интегрированную функциональность, мы все равно используем модель Pydantic для ручной генерации JSON Schema для данных, которые мы хотим получить в формате YAML. +Тем не менее, хотя мы не используем стандартную интегрированную функциональность, мы все же используем модель Pydantic, чтобы вручную сгенерировать JSON-схему для данных, которые мы хотим получить в YAML. -Затем мы используем запрос напрямую и извлекаем тело как `bytes`. Это означает, что FastAPI даже не пытается парсить полезную нагрузку запроса как JSON. +Затем мы используем запрос напрямую и извлекаем тело как `bytes`. Это означает, что FastAPI даже не будет пытаться парсить содержимое запроса как JSON. -А в нашем коде мы парсим содержимое YAML напрямую и затем снова используем ту же модель Pydantic для валидации содержимого YAML: +И затем в нашем коде мы парсим это YAML-содержимое напрямую, и затем снова используем ту же модель Pydantic для валидации содержимого YAML: //// tab | Pydantic v2 @@ -191,14 +191,14 @@ /// info | Информация -В версии Pydantic 1 метод для парсинга и валидации объекта назывался `Item.parse_obj()`, в версии Pydantic 2 этот метод называется `Item.model_validate()`. +В версии Pydantic 1 метод для парсинга и валидации объекта назывался `Item.parse_obj()`, в версии Pydantic 2 метод называется `Item.model_validate()`. /// /// tip | Совет -Здесь мы используем ту же самую модель Pydantic. +Здесь мы повторно используем ту же модель Pydantic. -Но таким же образом, мы могли бы валидировать ее и другим способом. +Но таким же образом можно было бы валидировать ее каким-то другим способом. /// diff --git a/docs/ru/docs/advanced/response-headers.md b/docs/ru/docs/advanced/response-headers.md index a4b62a1f2..d57b70c3e 100644 --- a/docs/ru/docs/advanced/response-headers.md +++ b/docs/ru/docs/advanced/response-headers.md @@ -1,41 +1,41 @@ -# Заголовки ответов +# HTTP-заголовки ответа -## Используйте параметр `Response` +## Использование параметра `Response` -Вы можете объявить параметр типа `Response` в вашей *функции обработки пути* (как вы можете сделать для cookies). +Вы можете объявить параметр типа `Response` в вашей *функции-обработчике пути* (так же, как вы делаете для cookie). -А затем вы можете установить заголовки в этом *временном* объекте ответа. +Затем вы можете установить HTTP-заголовки в этом *временном* объекте ответа. {* ../../docs_src/response_headers/tutorial002.py hl[1, 7:8] *} -И затем вы можете вернуть любой объект, который вам нужен, как вы обычно делаете (например, `dict`, модель базы данных и т.д.). +После этого вы можете вернуть любой объект, который вам нужен, как обычно (например, `dict`, модель базы данных и т.д.). -И если вы объявили `response_model`, он все равно будет использован для фильтрации и конвертации объекта, который вы вернули. +Если вы объявили `response_model`, он все равно будет использован для фильтрации и преобразования объекта, который вы вернули. -**FastAPI** использует этот *временный* ответ для извлечения заголовков (а также cookies и кода состояния) и помещает их в окончательный ответ, содержащий значение, которое вы вернули, отфильтрованное с помощью любого `response_model`. +**FastAPI** использует этот *временный* ответ для извлечения HTTP-заголовков (также cookie и статус-код ответа) и помещает их в окончательный ответ, который содержит значение, которое вы вернули и которое фильтруется любым `response_model`. -Вы также можете объявить параметр `Response` в зависимостях и установить заголовки (и cookies) в них. +Вы также можете объявить параметр `Response` в зависимостях и установить HTTP-заголовки (и cookie) в них. -## Возврат `Response` напрямую +## Непосредственный возврат `Response` -Вы также можете добавить заголовки, когда возвращаете `Response` напрямую. +Вы также можете добавить HTTP-заголовки при непосредственном возврате объекта типа `Response`. -Создайте ответ, как описано в разделе [Return a Response Directly](response-directly.md){.internal-link target=_blank} и передайте заголовки в качестве дополнительного параметра: +Создайте ответ, как описано в разделе [Непосредственный возврат ответа](response-directly.md){.internal-link target=_blank}, и передайте HTTP-заголовки в качестве дополнительного параметра: {* ../../docs_src/response_headers/tutorial001.py hl[10:12] *} /// note | Технические детали -Вы также можете использовать `from starlette.responses import Response` или `from starlette.responses import JSONResponse`. +Вы также могли бы использовать `from starlette.responses import Response` или `from starlette.responses import JSONResponse`. -**FastAPI** предоставляет те же `starlette.responses`, что и `fastapi.responses`, просто для вашего удобства, разработчика. Но большинство доступных ответов поступают непосредственно из Starlette. +**FastAPI** предоставляет те же `starlette.responses`, что и `fastapi.responses`, для удобства разработчика. Но большинство доступных ответов поступает непосредственно из Starlette. -И так как `Response` может часто использоваться для установки заголовков и cookies, **FastAPI** также предоставляет его в `fastapi.Response`. +И так как `Response` может часто использоваться для установки HTTP-заголовков и cookie, **FastAPI** также предоставляет его в `fastapi.Response`. /// ## Пользовательские заголовки -Имейте в виду, что пользовательские проприетарные заголовки могут быть добавлены с использованием префикса 'X-'. +Имейте в виду, что можно добавлять проприетарные пользовательские HTTP-заголовки с использованием префикса 'X-'. -Но если у вас есть пользовательские заголовки, которые вы хотите, чтобы клиент в браузере мог видеть, вам нужно добавить их в ваши CORS-конфигурации (подробнее читайте в [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), используя параметр `expose_headers`, задокументированный в документации Starlette о CORS. +Но если у вас есть пользовательские заголовки, которые вы хотите, чтобы клиент в браузере мог видеть, вам нужно добавить их в ваши CORS-настройки (прочтите больше в разделе [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), используя параметр `expose_headers`, документированный в документации Starlette по CORS. diff --git a/docs/ru/docs/advanced/security/http-basic-auth.md b/docs/ru/docs/advanced/security/http-basic-auth.md index 298324781..1a2e1d467 100644 --- a/docs/ru/docs/advanced/security/http-basic-auth.md +++ b/docs/ru/docs/advanced/security/http-basic-auth.md @@ -1,28 +1,28 @@ -# HTTP Базовая Аутентификация +# HTTP Basic Auth -Для самых простых случаев вы можете использовать HTTP Базовую Аутентификацию. +Для самых простых случаев можно использовать HTTP Basic Auth. -В HTTP Базовой Аутентификации, приложение ожидает заголовок, содержащий имя пользователя и пароль. +В HTTP Basic Auth приложение ожидает HTTP-заголовок, содержащий имя пользователя и пароль. -Если оно не получает его, то возвращает ошибку HTTP 401 "Unauthorized". +Если он не получит их, то вернет ошибку HTTP 401 "Unauthorized" (неавторизовано). -Также возвращается заголовок `WWW-Authenticate` со значением `Basic` и необязательный параметр `realm`. +Также будет возвращен HTTP-заголовок `WWW-Authenticate` со значением `Basic` и опциональным параметром `realm`. -Это сообщает браузеру показать встроенное окно запроса имени пользователя и пароля. +Это говорит браузеру показать встроенную панель для ввода имени пользователя и пароля. -Затем, когда вы вводите это имя пользователя и пароль, браузер отправляет их в заголовке автоматически. +Затем, когда вы вводите эти имя пользователя и пароль, браузер отправляет их в заголовке автоматически. -## Простая HTTP Базовая Аутентификация +## Простая HTTP Basic Auth * Импортируйте `HTTPBasic` и `HTTPBasicCredentials`. -* Создайте "`сущность` схемы безопасности" с использованием `HTTPBasic`. -* Используйте эту `схему безопасности` с зависимостью в вашем *путевом обработчике*. -* Это возвращает объект типа `HTTPBasicCredentials`: - * Он содержит `username` и `password`, которые были отправлены. +* Создайте "`security` scheme" используя `HTTPBasic`. +* Используйте эту `security` зависимость в вашей *операции пути*. +* Она возвращает объект типа `HTTPBasicCredentials`: + * Содержит отправленные `username` и `password`. {* ../../docs_src/security/tutorial006_an_py39.py hl[4,8,12] *} -Когда вы попробуете открыть URL в первый раз (или нажмёте кнопку "Execute" в документации), браузер запросит у вас ввод имени пользователя и пароля: +Когда вы попытаетесь открыть URL в первый раз (или нажмете кнопку "Execute" в документации) браузер спросит вас имя пользователя и пароль: @@ -30,15 +30,15 @@ Вот более полный пример. -Используйте зависимость, чтобы проверить, правильны ли имя пользователя и пароль. +Используйте зависимость, чтобы проверить, правильные ли имя пользователя и пароль. -Для этого используйте стандартный модуль Python `secrets`, чтобы проверить имя пользователя и пароль. +Для этого используйте стандартный модуль Python `secrets` для проверки имени пользователя и пароля. -`secrets.compare_digest()` должен принимать `bytes` или `str`, который содержит только символы ASCII (те, которые в английском языке), это значит, что он не будет работать с такими символами, как `á`, как в `Sebastián`. +`secrets.compare_digest()` требует `bytes` или `str`, содержащий только ASCII-символы (те, что на английском), это значит, что он не будет работать с символами, такими как `á`, например в `Sebastián`. -Чтобы обработать это, мы сначала преобразуем `username` и `password` в `bytes`, кодируя их с помощью UTF-8. +Чтобы с этим справиться, мы сначала конвертируем `username` и `password` в `bytes`, кодируя их в UTF-8. -Затем мы можем использовать `secrets.compare_digest()`, чтобы убедиться, что `credentials.username` равен `"stanleyjobson"`, а `credentials.password` равен `"swordfish"`. +Затем мы можем использовать `secrets.compare_digest()` для гарантии, что `credentials.username` равен `"stanleyjobson"`, а `credentials.password` равен `"swordfish"`. {* ../../docs_src/security/tutorial007_an_py39.py hl[1,12:24] *} @@ -46,62 +46,62 @@ ```Python if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"): - # Возвращаем какую-то ошибку + # Return some error ... ``` -Но, используя `secrets.compare_digest()`, это будет безопасно от типа атак, называемых "атаки по времени". +Но, используя `secrets.compare_digest()`, это будет защищено от атак под названием "тайминговые атаки". -### Атаки по времени +### Тайминговые атаки -Что же такое "атака по времени"? +Что такое "тайминговая атака"? -Представьте, что некоторые злоумышленники пытаются угадать имя пользователя и пароль. +Представим, что некоторая группа злоумышленников пытается угадать имя пользователя и пароль. -И они отправляют запрос с именем пользователя `johndoe` и паролем `love123`. +Они отправляют запрос с именем пользователя `johndoe` и паролем `love123`. -Тогда Python-код в вашем приложении будет аналогичен чему-то такому: +Тогда Python-код в вашем приложении будет эквивалентен чему-то вроде: ```Python if "johndoe" == "stanleyjobson" and "love123" == "swordfish": ... ``` -Но в тот момент, когда Python сравнивает первую `j` в `johndoe` с первой `s` в `stanleyjobson`, он вернёт `False`, потому что уже знает, что эти строки не одинаковы, считая, что "нет смысла тратить больше вычислений на сравнение оставшихся букв". И ваше приложение скажет "Неверное имя пользователя или пароль". +Но в тот момент, когда Python сравнивает первую `j` в `johndoe` с первой `s` в `stanleyjobson`, он вернет `False`, так как уже знает, что эти две строки не одинаковы, считая, что "нет смысла тратить больше вычислительных ресурсов на сравнение остальных букв". И ваше приложение скажет "Неправильное имя пользователя или пароль". -Но затем злоумышленники пробуют с именем пользователя `stanleyjobsox` и паролем `love123`. +Но затем злоумышленники попробуют с именем пользователя `stanleyjobsox` и паролем `love123`. -И ваш код в приложении делает что-то похожее: +И ваш код приложения делает что-то вроде: ```Python if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish": ... ``` -Python должен будет сравнить весь `stanleyjobso` в обоих `stanleyjobsox` и `stanleyjobson` перед тем, как осознать, что эти две строки не одинаковы. Поэтому для возвращения "Неверное имя пользователя или пароль" потребуется немного больше времени. +Python должен будет сравнить весь `stanleyjobso` в `stanleyjobsox` и `stanleyjobson`, чтобы понять, что строки не одинаковы. Так что это займет дополнительные микросекунды, чтобы ответить "Неправильное имя пользователя или пароль". #### Время ответа помогает злоумышленникам -В этот момент, заметив, что сервер потратил несколько микросекунд дольше для отправки ответа "Неверное имя пользователя или пароль", злоумышленники будут знать, что они угадали _что-то_ правильно, некоторые начальные буквы были правильными. +В этот момент, заметив, что серверу понадобилось немного больше времени, чтобы отправить ответ "Неправильное имя пользователя или пароль", злоумышленники узнают, что они что-то угадали, некоторые начальные буквы были правильными. -И затем они могут попробовать снова, зная, что это, вероятно, что-то больше похожее на `stanleyjobsox`, чем на `johndoe`. +И тогда они могут попробовать снова, зная, что это, вероятно, что-то более похожее на `stanleyjobsox`, чем на `johndoe`. #### "Профессиональная" атака -Конечно, злоумышленники не будут пробовать все это вручную, они напишут программу, чтобы сделать это, возможно, с тысячами или миллионами тестов в секунду. И они получат только одну дополнительную правильную букву за раз. +Конечно, злоумышленники не будут делать все это вручную, они напишут программу, чтобы делать это, возможно, с тысячами или миллионами тестов в секунду. И они будут получать лишь одну правильную букву за раз. -Но, делая это, за несколько минут или часов злоумышленники могут угадать правильное имя пользователя и пароль с "помощью" нашего приложения, просто используя время, взятое на ответ. +Но, делая так, за несколько минут или часов злоумышленники могли бы угадать правильное имя пользователя и пароль, с "помощью" нашего приложения, просто используя время, затраченное на ответ. #### Исправьте это с помощью `secrets.compare_digest()` Но в нашем коде мы фактически используем `secrets.compare_digest()`. -Вкратце, это займет одинаковое время для сравнения `stanleyjobsox` с `stanleyjobson`, как и для сравнения `johndoe` с `stanleyjobson`. И то же самое для пароля. +Вкратце, это займет одинаковое время, чтобы сравнить `stanleyjobsox` с `stanleyjobson`, как и `johndoe` с `stanleyjobson`. И то же самое для пароля. -Таким образом, используя `secrets.compare_digest()` в вашем коде приложения, оно будет безопасным от всего этого множества атак на безопасность. +Таким образом, используя `secrets.compare_digest()` в коде вашего приложения, оно будет защищено от этого целого спектра атак на безопасность. -### Возвращение ошибки +### Возврат ошибки -После обнаружения, что учетные данные неверны, верните `HTTPException` со статусным кодом 401 (тем же, что возвращается, когда учетные данные не предоставлены) и добавьте заголовок `WWW-Authenticate`, чтобы заставить браузер снова показать приглашение о вводе данных: +После обнаружения, что учетные данные неверны, верните `HTTPException` с кодом состояния 401 (тот же, что возвращается, когда учетные данные не предоставлены) и добавьте заголовок `WWW-Authenticate`, чтобы браузер снова отобразил приглашение для входа: {* ../../docs_src/security/tutorial007_an_py39.py hl[26:30] *} diff --git a/docs/ru/docs/advanced/security/index.md b/docs/ru/docs/advanced/security/index.md index ea32fbac0..9d681c7fd 100644 --- a/docs/ru/docs/advanced/security/index.md +++ b/docs/ru/docs/advanced/security/index.md @@ -2,18 +2,18 @@ ## Дополнительные функции -Существуют дополнительные функции для обеспечения безопасности, помимо тех, которые рассмотрены в [Учебнике - Руководстве пользователя: Безопасность](../../tutorial/security/index.md){.internal-link target=_blank}. +Существуют дополнительные функции для обеспечения безопасности, кроме тех, которые рассмотрены в [Руководстве пользователя: Безопасность](../../tutorial/security/index.md){.internal-link target=_blank}. /// tip | Совет Следующие разделы **не обязательно "продвинутые"**. -И возможно, что решение для вашего случая использования находится в одном из них. +И возможно, что для вашего случая решения находятся в одном из них. /// -## Сначала прочитайте Учебник +## Сначала прочтите Руководство -Следующие разделы предполагают, что вы уже прочитали основной [Учебник - Руководство пользователя: Безопасность](../../tutorial/security/index.md){.internal-link target=_blank}. +Следующие разделы предполагают, что вы уже прочитали основное [Руководство пользователя: Безопасность](../../tutorial/security/index.md){.internal-link target=_blank}. -Все они основаны на тех же концепциях, но позволяют добавить дополнительные функции. +Все они основаны на тех же концепциях, но позволяют использовать некоторые дополнительные функции. diff --git a/docs/ru/docs/advanced/security/oauth2-scopes.md b/docs/ru/docs/advanced/security/oauth2-scopes.md index c75b1e008..9a2b7f203 100644 --- a/docs/ru/docs/advanced/security/oauth2-scopes.md +++ b/docs/ru/docs/advanced/security/oauth2-scopes.md @@ -1,66 +1,66 @@ -# OAuth2 области +# OAuth2 scope -Вы можете использовать OAuth2 области непосредственно с **FastAPI**, они интегрированы для бесшовной работы. +Вы можете использовать OAuth2 scope напрямую с **FastAPI**, они интегрированы для работы без проблем. -Это позволит вам иметь более детализированную систему разрешений, следуя стандарту OAuth2, интегрированному в ваше приложение OpenAPI (и API-документацию). +Это позволит вам иметь более тонкую систему разрешений, следуя стандарту OAuth2, интегрированную в ваше OpenAPI приложение (и документы API). -OAuth2 с областями — это механизм, используемый многими крупными поставщиками аутентификации, такими как Facebook, Google, GitHub, Microsoft, Twitter и др. Они используют его, чтобы предоставить пользователям и приложениям доступ к определённым разрешениям. +OAuth2 с scope — это механизм, используемый многими крупными провайдерами аутентификации, такими как Facebook, Google, GitHub, Microsoft, Twitter и т.д. Они используют его для предоставления определенных разрешений пользователям и приложениям. -Каждый раз, когда вы "входите через" Facebook, Google, GitHub, Microsoft, Twitter, это приложение использует OAuth2 с областями. +Каждый раз, когда вы "входите с помощью" Facebook, Google, GitHub, Microsoft, Twitter, это приложение использует OAuth2 с scope. -В этом разделе вы узнаете, как управлять аутентификацией и авторизацией с помощью тех же OAuth2 областей в вашем приложении на **FastAPI**. +В этом разделе вы увидите, как управлять аутентификацией и авторизацией с использованием того же OAuth2 с scope в вашем приложении **FastAPI**. /// warning | Предупреждение -Это более или менее продвинутый раздел. Если вы только начинаете, вы можете его пропустить. +Это более или менее сложный раздел. Если вы только начинаете, вы можете пропустить его. -Вам не обязательно нужны OAuth2 области, и вы можете обрабатывать аутентификацию и авторизацию так, как вам удобно. +Вы не обязательно нуждаетесь в OAuth2 scope, и можете обрабатывать аутентификацию и авторизацию, как вам угодно. -Но OAuth2 с областями можно красиво интегрировать в ваш API (с OpenAPI) и в вашу API-документацию. +Но OAuth2 с scope может быть прекрасно интегрирован в ваш API (с OpenAPI) и в ваши документы API. -Тем не менее, вы всё равно соблюдаете эти области или любое другое требование безопасности/авторизации, как вам нужно, в вашем коде. +Тем не менее, вы все равно должны применять эти scope, или любые другие требования к безопасности/авторизации, так как вам нужно, в вашем коде. -Во многих случаях, OAuth2 с областями может быть излишен. +В многих случаях, OAuth2 с scope может быть избыточными. -Но если вы знаете, что он вам нужен, или вы просто любопытны, продолжайте читать. +Но если вы знаете, что они вам нужны, или вы заинтересовались, продолжайте чтение. /// -## OAuth2 области и OpenAPI +## OAuth2 scope и OpenAPI -Спецификация OAuth2 определяет "области" как список строк, разделённых пробелами. +Спецификация OAuth2 определяет "scope" как список строк, разделенных пробелами. Содержимое каждой из этих строк может иметь любой формат, но не должно содержать пробелов. -Эти области представляют собой "разрешения". +Эти scope представляют собой "разрешения". -В OpenAPI (например, в API-документации) вы можете определить "схемы безопасности". +В OpenAPI (например, в документах API) вы можете определить "схемы безопасности". -Когда одна из этих схем безопасности использует OAuth2, вы также можете определить и использовать области. +Когда одна из этих схем безопасности использует OAuth2, вы также можете объявлять и использовать scope. -Каждая "область" — это просто строка (без пробелов). +Каждый "scope" — это просто строка (без пробелов). -Они обычно используются для определения конкретных разрешений безопасности, например: +Обычно они используются для объявления определенных разрешений безопасности, например: -* `users:read` или `users:write` — это общие примеры. -* `instagram_basic` используется Facebook / Instagram. +* `users:read` или `users:write` — это распространенные примеры. +* `instagram_basic` используется Facebook/Instagram. * `https://www.googleapis.com/auth/drive` используется Google. /// info | Информация -В OAuth2 "область" — это просто строка, которая декларирует необходимое специфическое разрешение. +В OAuth2 "scope" — это просто строка, указывающая на конкретные требуемые разрешения. -Неважно, есть ли у неё другие символы, такие как `:`, или если это URL. +Не имеет значения, есть ли в нем другие символы, такие как `:`, или если это URL. -Эти детали зависят от реализации. +Эти детали специфичны для реализации. Для OAuth2 они просто строки. /// -## Глобальный обзор +## Общее представление -Во-первых, быстро рассмотрим части, которые изменяются в примерах в основном **Учебнике - Руководстве пользователя** для [OAuth2 с паролем (и хешированием), носитель с JWT токенами](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. Теперь используя OAuth2 области: +Сначала давайте быстро посмотрим на части, которые изменяются по сравнению с примерами в основном **Учебнике - Руководстве пользователя** для [OAuth2 с Паролем (и хешированием), Bearer с JWT токенами](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. Теперь используя OAuth2 scope: {* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:125,129:135,140,156] *} @@ -68,59 +68,59 @@ OAuth2 с областями — это механизм, используемы ## Схема безопасности OAuth2 -Первое изменение заключается в том, что теперь мы объявляем схему безопасности OAuth2 с двумя доступными областями, `me` и `items`. +Первое изменение состоит в том, что мы теперь объявляем схему безопасности OAuth2 с двумя доступными scope, `me` и `items`. -Параметр `scopes` принимает `dict` с каждой областью в качестве ключа и описанием в качестве значения: +Параметр `scopes` принимает `dict`, где каждый scope указывается в качестве ключа, а описание — в качестве значения: {* ../../docs_src/security/tutorial005_an_py310.py hl[63:66] *} -Поскольку мы теперь объявляем эти области, они будут отображаться в API-документации, когда вы войдете/авторизуетесь. +Поскольку мы теперь объявляем эти scope, они будут отображаться в документации API, когда вы входите/авторизируетесь. -И вы сможете выбрать, к каким областям вы хотите предоставить доступ: `me` и `items`. +И вы сможете выбрать, к каким scope вы хотите дать доступ: `me` и `items`. -Это тот же механизм, который используется при предоставлении разрешений при входе через Facebook, Google, GitHub и т.д.: +Это тот же механизм, который используется, когда вы предоставляете разрешения при входе в Facebook, Google, GitHub и т.д: -## JWT токен с областями +## JWT токен с scope -Теперь измените *path operation*, чтобы вернуть запрошенные области. +Теперь модифицируйте токен *операции пути*, чтобы вернуть запрашиваемые scope. -Мы всё ещё используем тот же `OAuth2PasswordRequestForm`. Он включает собственность `scopes` со `списком` `str`, с каждой областью, полученной в запросе. +Мы по-прежнему используем тот же `OAuth2PasswordRequestForm`. Он включает свойство `scopes` с `list` из `str`, в котором содержатся все scope, полученные в запросе. -И мы возвращаем области как часть JWT токена. +И мы возвращаем scope как часть JWT токена. /// danger | Опасность -Для простоты, здесь мы просто добавляем области, полученные напрямую в токен. +Для упрощения, здесь мы просто добавляем полученные scope непосредственно в токен. -Но в вашем приложении, для безопасности, вы должны убедиться, что добавляете только те области, которые пользователь действительно может иметь, или те, которые вы предопределили. +Но в вашем приложении, с целью безопасности, вы должны удостовериться, что добавляете только те scope, которые пользователь действительно может иметь, или те, которые вы заранее определили. /// {* ../../docs_src/security/tutorial005_an_py310.py hl[156] *} -## Объявление областей в *path operations* и зависимостях +## Объявление scope в *операциях пути* и зависимостях -Теперь мы объявляем, что *path operation* для `/users/me/items/` требует область `items`. +Теперь мы объявляем, что *операция пути* для `/users/me/items/` требует scope `items`. Для этого мы импортируем и используем `Security` из `fastapi`. -Вы можете использовать `Security` для объявления зависимостей (так же, как `Depends`), но `Security` также получает параметр `scopes` со списком областей (строк). +Вы можете использовать `Security` для объявления зависимостей (так же как `Depends`), но `Security` также принимает параметр `scopes` со списком scope (строк). -В этом случае мы передаем функцию зависимости `get_current_active_user` в `Security` (так же, как мы бы делали с `Depends`). +В данном случае, мы передаем функцию зависимости `get_current_active_user` в `Security` (так же как мы бы делали это с `Depends`). -Но мы также передаем `список` областей, в этом случае только одну область: `items` (их могло бы быть больше). +Но мы также передаем `list` с scope, в этом случае только с одним scope: `items` (хотя их может быть больше). -И функция зависимости `get_current_active_user` также может объявлять подзависимости, не только с помощью `Depends`, но и с помощью `Security`. Объявляя свою подзависимую функцию (`get_current_user`), и дополнительные требования к областям. +И функция зависимости `get_current_active_user` также может объявлять подзависимости, не только с `Depends`, но и с `Security`. Объявляя свою подзависимость (`get_current_user`), а также требования к scope. -В этом случае требуется область `me` (могло бы требоваться более одной области). +В этом случае требуется scope `me` (могут требоваться и другие scope). /// note | Примечание -Вам не обязательно нужно добавлять разные области в разных местах. +Вам не обязательно нужно добавлять разные scope в разные места. -Мы делаем это здесь, чтобы продемонстрировать, как **FastAPI** обрабатывает области, объявленные на разных уровнях. +Мы делаем это здесь, чтобы продемонстрировать, как **FastAPI** обрабатывает scope, объявленные на разных уровнях. /// @@ -128,27 +128,27 @@ OAuth2 с областями — это механизм, используемы /// info | Технические детали -`Security` на самом деле является подклассом `Depends`, и имеет только один дополнительный параметр, который мы увидим позже. +`Security` на самом деле является подклассом `Depends`, и у него есть всего один дополнительный параметр, который мы рассмотрим позже. -Но используя `Security` вместо `Depends`, **FastAPI** распознает, что можно объявлять области безопасности, использовать их внутри и документировать API с помощью OpenAPI. +Но используя `Security` вместо `Depends`, **FastAPI** будет знать, что он может объявить scope безопасности, использовать их внутри и документировать API с помощью OpenAPI. Но когда вы импортируете `Query`, `Path`, `Depends`, `Security` и другие из `fastapi`, это на самом деле функции, которые возвращают специальные классы. /// -## Использование `SecurityScopes` +## Используйте `SecurityScopes` Теперь обновите зависимость `get_current_user`. -Эта функция используется приведёнными выше зависимостями. +Это та зависимость, которая используется выше. -Здесь мы используем ту же схему OAuth2, которую создали ранее, объявляя её как зависимость: `oauth2_scheme`. +Вот где мы используем ту же схему OAuth2, которую создали ранее, объявляя ее как зависимость: `oauth2_scheme`. -Поскольку эта функция зависимости сама по себе не имеет требований к областям, мы можем использовать `Depends` с `oauth2_scheme`, нам не нужно использовать `Security`, когда нам не нужно указывать области безопасности. +Поскольку эта функция зависимости не имеет собственных требований к scope, мы можем использовать `Depends` с `oauth2_scheme`, нам не нужно использовать `Security`, когда нам не нужно указывать scope безопасности. -Мы также объявляем специальный параметр типа `SecurityScopes`, импортированный из `fastapi.security`. +Также мы объявляем специальный параметр типа `SecurityScopes`, импортированный из `fastapi.security`. -Этот класс `SecurityScopes` аналогичен `Request` (в `Request` использовался объект запроса напрямую). +Этот класс `SecurityScopes` похож на `Request` (`Request` использовался для получения объекта запроса напрямую). {* ../../docs_src/security/tutorial005_an_py310.py hl[9,106] *} @@ -156,119 +156,119 @@ OAuth2 с областями — это механизм, используемы Параметр `security_scopes` будет типа `SecurityScopes`. -Он будет иметь свойство `scopes` со списком всех областей, требуемых самой функцией и всеми зависимостями, использующими её как подзависимость. Это значит, все "зависящие"... это может звучать запутанно, ниже объясняется подробнее. +У него есть свойство `scopes` со списком, содержащим все scope, требуемые как сама зависимость, так и все зависимости, которые используют это как подзависимость. Это значит, все "зависимые"... это может звучать запутанно, но это объясняется снова позже. -Объект `security_scopes` (класса `SecurityScopes`) также предоставляет атрибут `scope_str` с одной строкой, содержащей эти области, разделённые пробелами (мы его используем). +Объект `security_scopes` (класса `SecurityScopes`) также предоставляет атрибут `scope_str` с одной строкой, содержащей эти scope, разделенные пробелами (мы собираемся использовать его). -Мы создаём `HTTPException`, который можем использовать (`raise`) позже в некоторых точках. +Мы создаем `HTTPException`, который мы можем использовать (`raise`) позже в нескольких повторяющихся моментах. -В этом исключении мы включаем требуемые области (если они есть) в виде строки, разделённой пробелами (используя `scope_str`). Мы помещаем эту строку, содержащую области, в заголовок `WWW-Authenticate` (это часть спецификации). +В этом исключении мы включаем требуемые scope (если они есть) в виде строки, разделенной пробелами (используя `scope_str`). Мы помещаем эту строку, содержащую scope, в HTTP-заголовке `WWW-Authenticate` (это часть спецификации). {* ../../docs_src/security/tutorial005_an_py310.py hl[106,108:116] *} -## Проверка `username` и формы данных +## Проверьте `username` и форму данных -Мы проверяем, что получили `username`, и извлекаем области. +Мы проверяем, что получили `username`, и извлекаем scope. -А затем мы валидируем эти данные с помощью модели Pydantic (отлавливая исключение `ValidationError`), и если у нас есть ошибка чтения JWT токена или валидирования данных с помощью Pydantic, мы возбуждаем созданное ранее `HTTPException`. +Затем мы валидируем эти данные с помощью Pydantic-модели (обрабатывая исключение `ValidationError`), и если мы получаем ошибку при чтении JWT токена или валидации данных с Pydantic, мы вызываем `HTTPException`, который создали ранее. -Для этого мы обновляем модель Pydantic `TokenData`, добавив новое свойство `scopes`. +Для этого мы обновляем Pydantic-модель `TokenData` с новым свойством `scopes`. -Валидируя данные с помощью Pydantic, мы можем убедиться, что у нас есть, например, именно `список` `str` с областями и `str` с `username`. +Валидируя данные с помощью Pydantic, мы можем убедиться, что у нас, например, точно есть `list` из `str` с scope и `str` с `username`. -Вместо, например, `dict`, или чего-то ещё, что могло бы в какой-то момент сломать приложение, создавая риск безопасности. +Вместо, например, `dict`, или чего-то еще, так как это может сломать приложение в какой-то момент позже, создавая угрозу безопасности. -Мы также проверяем, что у нас есть пользователь с этим именем пользователя, и если нет, мы возбуждаем то же исключение, которое создали ранее. +Мы также проверяем, что у нас есть пользователь с этим именем пользователя, и если нет, вызываем то же самое исключение, созданное ранее. {* ../../docs_src/security/tutorial005_an_py310.py hl[47,117:128] *} -## Проверка `scopes` +## Проверьте `scopes` -Теперь проверяем, что все области, требуемые этой зависимостью и всеми зависимыми (включая *path operations*), включены в области, предоставленные в полученном токене, в противном случае возбуждаем `HTTPException`. +Теперь мы проверяем, все ли требуемые scope, этой зависимостью и всеми зависимыми (включая *операции пути*), включены в предоставленные токеном scope, в противном случае вызываем `HTTPException`. -Для этого используем `security_scopes.scopes`, который содержит `список` со всеми этими областями как `str`. +Для этого мы используем `security_scopes.scopes`, который содержит `list` со всеми этими scope как `str`. {* ../../docs_src/security/tutorial005_an_py310.py hl[129:135] *} -## Дерево зависимостей и области +## Дерево зависимостей и scope -Давайте снова рассмотрим это дерево зависимостей и области. +Давайте еще раз рассмотрим это дерево зависимостей и scope. -Поскольку зависимость `get_current_active_user` имеет подзависимость `get_current_user`, область `"me"`, объявленная в `get_current_active_user`, будет включена в `список` требуемых областей в `security_scopes.scopes`, переданный `get_current_user`. +Поскольку зависимость `get_current_active_user` имеет подзависимость на `get_current_user`, scope `"me"`, объявленный в `get_current_active_user`, будет включен в список требуемых scope в `security_scopes.scopes`, переданном в `get_current_user`. -*Path operation* также объявляет область, `"items"`, так что это тоже будет в `списке` `security_scopes.scopes`, переданный `get_current_user`. +Сама *операция пути* также объявляет scope, `"items"`, так что он также будет в списке `security_scopes.scopes`, передаваемом в `get_current_user`. -Вот как выглядит иерархия зависимостей и областей: +Вот как выглядит иерархия зависимостей и scope: -* *Path operation* `read_own_items` имеет: - * Требуемые области `["items"]` с зависимостью: +* У *операции пути* `read_own_items`: + * Требуемые scope `["items"]` с зависимостью: * `get_current_active_user`: * Функция зависимости `get_current_active_user` имеет: - * Требуемые области `["me"]` с зависимостью: + * Требуемые scope `["me"]` с зависимостью: * `get_current_user`: - * Функция зависимости `get_current_user` имеет: - * Нет требуемых собственной области. - * Зависимость, использующую `oauth2_scheme`. + * У функции зависимости `get_current_user`: + * Нет требуемых scope. + * Зависимость, использующая `oauth2_scheme`. * Параметр `security_scopes` типа `SecurityScopes`: - * Этот параметр `security_scopes` имеет свойство `scopes` с `списком`, содержащим все выше указанные области, так что: - * `security_scopes.scopes` будет содержать `["me", "items"]` для *path operation* `read_own_items`. - * `security_scopes.scopes` будет содержать `["me"]` для *path operation* `read_users_me`, потому что она объявлена в зависимости `get_current_active_user`. - * `security_scopes.scopes` будет содержать `[]` (ничего) для *path operation* `read_system_status`, потому что она не объявляет никакой `Security` с `scopes`, а её зависимость `get_current_user` также не объявляет никаких `scopes`. + * У этого параметра `security_scopes` есть свойство `scopes` со `list`, содержащим все scope, объявленные выше, так что: + * `security_scopes.scopes` будет содержать `["me", "items"]` для *операции пути* `read_own_items`. + * `security_scopes.scopes` будет содержать `["me"]` для *операции пути* `read_users_me`, потому что он объявлен в зависимости `get_current_active_user`. + * `security_scopes.scopes` будет содержать `[]` (ничего) для *операции пути* `read_system_status`, потому что там не объявлено никакое `Security` с `scopes`, и его зависимость `get_current_user` также не объявляет никакие `scopes`. -/// tip | Подсказка +/// tip | Совет -Самое важное и "магическое" здесь то, что `get_current_user` будет иметь различный список `scopes` для проверки для каждого *path operation*. +Самое важное и "магическое" здесь то, что `get_current_user` будет иметь разный список `scopes` для проверки для каждой *операции пути*. -Всё зависит от `scopes`, объявленных в каждом *path operation* и каждой зависимости в дереве зависимостей для этого конкретного *path operation*. +Все зависит от `scopes`, объявленных в каждой *операции пути* и каждой зависимости в дереве зависимостей для данной конкретной *операции пути*. /// -## Больше деталей об `SecurityScopes` +## Подробности о `SecurityScopes` -Вы можете использовать `SecurityScopes` в любой точке, и в нескольких местах, не обязательно на "корневой" зависимости. +Вы можете использовать `SecurityScopes` в любой точке и в нескольких местах, он не должен быть на уровне "корневой" зависимости. -Оно всегда будет иметь области безопасности, объявленные в текущих `Security` зависимостях и все зависимые для **этого конкретного** *path operation* и **этого конкретного** дерева зависимостей. +Он будет всегда иметь scope безопасности, объявленные в текущих зависимостях `Security` и всех зависимых для **конкретно этой** *операции пути* и **конкретно этого** дерева зависимостей. -Поскольку `SecurityScopes` будут иметь все области, объявленные зависимыми, вы можете использовать его для проверки, что токен имеет требуемые области в центральной функции зависимости, а затем объявить различные требования к областям в различных *path operations*. +Поскольку `SecurityScopes` будут иметь все scope, заявленные зависимыми, вы можете использовать его для проверки того, что токен имеет требуемые scope в центральной функции зависимости, а затем объявлять разные требования к scope в разных *операциях пути*. -Они будут проверяться независимо для каждого *path operation*. +Они будут проверяться независимо для каждой *операции пути*. ## Проверьте это -Если откроете API-документацию, вы можете пройти аутентификацию и указать, какие области хотите авторизовать. +Если вы откроете документацию API, вы можете аутентифицироваться и указать, какие scope вы хотите авторизовать. -Если вы не выберете ни одной области, вы будете "аутентифицированы", но при попытке получить доступ к `/users/me/` или `/users/me/items/` вы получите ошибку, говоря, что у вас недостаточно разрешений. Вы всё ещё сможете получить доступ к `/status/`. +Если вы не выберете ни один scope, вы будете "аутентифицированы", но при попытке доступа к `/users/me/` или `/users/me/items/` вы получите ошибку, сообщающую, что у вас недостаточно разрешений. Вы все равно сможете получить доступ к `/status/`. -И если вы выберете область `me`, но не `items`, вы сможете получить доступ к `/users/me/`, но не к `/users/me/items/`. +И если вы выберете scope `me`, но не scope `items`, вы сможете получить доступ к `/users/me/`, но не к `/users/me/items/`. -Вот что произойдёт с приложениями третьих сторон, которые пытались бы получить доступ к одной из этих *path operations* с токеном, предоставленным пользователем, в зависимости от того, сколько разрешений пользователь дал приложению. +Это именно то, что произойдет с сторонним приложением, которое пытается получить доступ к одной из этих *операций пути* с токеном, предоставленным пользователем, в зависимости от того, сколько разрешений пользователь дал приложению. ## О сторонних интеграциях -В этом примере мы используем "парольный" поток OAuth2. +В этом примере мы используем OAuth2 "парольный" поток. -Это уместно, когда мы входим в наше собственное приложение, вероятно, с нашим собственным интерфейсом. +Это уместно, когда мы входим в наше собственное приложение, вероятно, с нашим собственным фронтендом. Потому что мы можем доверять ему получение `username` и `password`, так как мы его контролируем. -Но если вы создаёте OAuth2 приложение, к которому будут подключаться другие (то есть, если вы создаёте поставщика аутентификации, эквивалентного Facebook, Google, GitHub и т.д.), вы должны использовать один из других потоков. +Но если вы строите приложение OAuth2, к которому будут подключаться другие (т.е. если вы создаете провайдер аутентификации, эквивалентный Facebook, Google, GitHub и т.д.), вы должны использовать один из других потоков. -Наиболее распространенный — это неявный поток. +Наиболее распространенным является поток implicit. -Наиболее безопасный — это поток с кодом, но его сложнее реализовать, так как он требует больше шагов. Из-за сложности многие провайдеры в конечном итоге рекомендуют неявный поток. +Наиболее безопасным является поток с кодом, но его сложнее реализовать, так как он требует больше шагов. Поскольку он более сложен, многие провайдеры в конечном итоге предлагают поток implicit. /// note | Примечание -Часто каждый поставщик аутентификации называет свои потоки по-разному, чтобы сделать это частью их бренда. +Часто каждый провайдер аутентификации называет свои потоки по-разному, чтобы сделать это частью своего бренда. -Но в конце концов, они реализуют тот же стандарт OAuth2. +Но в конечном итоге они реализуют тот же стандарт OAuth2. /// **FastAPI** включает утилиты для всех этих потоков аутентификации OAuth2 в `fastapi.security.oauth2`. -## `Security` в бедператора `dependencies` +## `Security` в `dependencies` декоратора -Так же, как вы можете определить `список` `Depends` в параметре `dependencies` там бедператора (как объясняется в [Зависимости в бедператорaх path operation](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}), вы также можете использовать `Security` с `scopes` там. +Таким же образом, как вы можете определять `list` из `Depends` в параметре `dependencies` декоратора (как объяснено в [Dependencies в декораторах операций пути](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}), вы также можете использовать `Security` с `scopes` там. diff --git a/docs/ru/docs/advanced/settings.md b/docs/ru/docs/advanced/settings.md index 6083904cd..7bbeff158 100644 --- a/docs/ru/docs/advanced/settings.md +++ b/docs/ru/docs/advanced/settings.md @@ -1,30 +1,30 @@ # Настройки и переменные окружения -Во многих случаях вашему приложению могут потребоваться внешние настройки или конфигурации, например, секретные ключи, учетные данные для базы данных, учетные данные для сервисов электронной почты и так далее. +Во многих случаях вашим приложениям могут понадобиться внешние настройки или конфигурации, например, секретные ключи, учетные данные базы данных, учетные данные для почтовых сервисов и т.д. -Большинство из этих настроек переменные (могут изменяться), как, например, URL базы данных. И многие могут быть конфиденциальными, как секреты. +Большинство этих настроек являются изменяемыми (могут изменяться), как, например, URL-ы баз данных. Многие из них могут быть чувствительными, как, например, секреты. -По этой причине их обычно предоставляют в переменных окружения, которые считываются приложением. +По этой причине их обычно предоставляют в виде переменных окружения, которые считываются приложением. /// tip | Совет -Чтобы понять переменные окружения, вы можете прочитать [Переменные окружения](../environment-variables.md){.internal-link target=_blank}. +Чтобы понять, что такое переменные окружения, можете прочитать [Переменные окружения](../environment-variables.md){.internal-link target=_blank}. /// ## Типы и валидация -Эти переменные окружения могут обрабатывать только текстовые строки, так как они находятся вне Python и должны быть совместимы с другими программами и остальной системой (и даже с различными операционными системами, такими как Linux, Windows, macOS). +Эти переменные окружения могут обрабатывать только текстовые строки, так как они являются внешними для Python и должны быть совместимы с другими программами и остальной системой (и даже с разными операционными системами, такими как Linux, Windows, macOS). -Это значит, что любое значение, считанное в Python из переменной окружения, будет `str`, и любая конвертация в другой тип или любая валидация должна выполняться в коде. +Это означает, что любое значение, считанное в Python из переменной окружения, будет типа `str`, и любое преобразование в другой тип или валидация должны осуществляться в коде. ## Pydantic `Settings` -К счастью, Pydantic предоставляет отличную утилиту для работы с этими настройками, поступающими из переменных окружения, с помощью Pydantic: Управление настройками. +К счастью, Pydantic предоставляет отличную утилиту для работы с этими настройками, поступающими из переменных окружения, используя Pydantic: Управление настройками. ### Установка `pydantic-settings` -Сначала убедитесь, что вы создали свое [виртуальное окружение](../virtual-environments.md){.internal-link target=_blank}, активировали его, а затем установили пакет `pydantic-settings`: +Сначала убедитесь, что вы создали ваше [виртуальное окружение](../virtual-environments.md){.internal-link target=_blank}, активировали его и затем установили пакет `pydantic-settings`:
@@ -35,7 +35,7 @@ $ pip install pydantic-settings
-Он также включен при установке `all`-дополнений с: +Этот пакет также включен, если вы устанавливаете все зависимости с:
@@ -48,17 +48,17 @@ $ pip install "fastapi[all]" /// info | Информация -В Pydantic v1 он был включен в основной пакет. Теперь он распространяется как независимый пакет, чтобы вы могли выбрать, устанавливать его или нет, если вам эта функциональность не нужна. +В Pydantic v1 он поставлялся с основным пакетом. Теперь он распространяется как отдельный пакет, чтобы вы могли выбрать, устанавливать его или нет, если вам не нужна эта функциональность. /// ### Создание объекта `Settings` -Импортируйте `BaseSettings` из Pydantic и создайте подкласс, аналогично модели Pydantic. +Импортируйте `BaseSettings` из Pydantic и создайте подкласс, как это делается с Pydantic-моделью. -Так же, как с моделями Pydantic, вы объявляете атрибуты класса с аннотациями типов и, возможно, значениями по умолчанию. +Так же, как и с Pydantic-моделями, вы объявляете атрибуты класса с аннотациями типов и, возможно, значениями по умолчанию. -Вы можете использовать все те же функции и инструменты валидации, что и для моделей Pydantic, такие как различные типы данных и дополнительные проверки с помощью `Field()`. +Вы можете использовать все те же функции валидации и инструменты, которые используете в Pydantic-моделях, например, разные типы данных и дополнительные валидации с `Field()`. //// tab | Pydantic v2 @@ -70,7 +70,7 @@ $ pip install "fastapi[all]" /// info | Информация -В Pydantic v1 вы бы импортировали `BaseSettings` непосредственно из `pydantic` вместо `pydantic_settings`. +В Pydantic v1 вы импортировали бы `BaseSettings` непосредственно из `pydantic` вместо `pydantic_settings`. /// @@ -80,13 +80,13 @@ $ pip install "fastapi[all]" /// tip | Совет -Если вы хотите что-то быстрое для копирования и вставки, не используйте этот пример, воспользуйтесь последним ниже. +Если вам нужно что-то быстрое для копирования и вставки, не используйте этот пример, используйте последний ниже. /// -Затем, когда вы создадите экземпляр этого класса `Settings` (в данном случае в объекте `settings`), Pydantic будет читать переменные окружения без учета регистра, так что переменная в верхнем регистре `APP_NAME` будет прочитана для атрибута `app_name`. +Когда вы создаете экземпляр этого класса `Settings` (в данном случае, в объекте `settings`), Pydantic будет считывать переменные окружения без учета регистра, так что переменная в верхнем регистре `APP_NAME` все еще будет считана для атрибута `app_name`. -Затем он преобразует и проверит данные. Таким образом, когда вы используете этот объект `settings`, у вас будут данные тех типов, которые вы объявили (например, `items_per_user` будет `int`). +Затем он выполнит преобразование и валидацию данных. Таким образом, когда вы используете этот объект `settings`, у вас будут данные тех типов, которые вы объявили (например, `items_per_user` будет типа `int`). ### Использование `settings` @@ -96,7 +96,7 @@ $ pip install "fastapi[all]" ### Запуск сервера -Затем вы бы запустили сервер, передавая конфигурации в качестве переменных окружения, например, вы могли бы установить `ADMIN_EMAIL` и `APP_NAME` с помощью: +Далее вы можете запустить сервер, передавая конфигурации как переменные окружения, например, вы можете установить `ADMIN_EMAIL` и `APP_NAME` следующим образом:
@@ -110,43 +110,43 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p /// tip | Совет -Чтобы установить несколько переменных окружения для одной команды, просто разделите их пробелом и укажите все перед командой. +Чтобы установить несколько переменных окружения для одной команды, просто разделите их пробелами и укажите перед командой. /// -И затем `admin_email` будет установлен на `"deadpool@example.com"`. +Тогда настройка `admin_email` будет установлена в `"deadpool@example.com"`. -`app_name` будет `"ChimichangApp"`. +Настройка `app_name` будет иметь значение `"ChimichangApp"`. -А `items_per_user` сохранит свое значение по умолчанию `50`. +А `items_per_user` сохранит свое значение по умолчанию — `50`. ## Настройки в другом модуле -Вы можете поместить эти настройки в другом файле модуля, как вы видели в [Большие приложения - Несколько файлов](../tutorial/bigger-applications.md){.internal-link target=_blank}. +Вы можете поместить эти настройки в другой файл-модуль, как вы видели в [Более крупные приложения - Несколько файлов](../tutorial/bigger-applications.md){.internal-link target=_blank}. Например, у вас может быть файл `config.py` с: {* ../../docs_src/settings/app01/config.py *} -А затем использовать в файле `main.py`: +И затем использовать его в файле `main.py`: {* ../../docs_src/settings/app01/main.py hl[3,11:13] *} /// tip | Совет -Вам также понадобится файл `__init__.py`, как вы видели в [Большие приложения - Несколько файлов](../tutorial/bigger-applications.md){.internal-link target=_blank}. +Вам также нужен будет файл `__init__.py`, как вы видели в [Более крупные приложения - Несколько файлов](../tutorial/bigger-applications.md){.internal-link target=_blank}. /// ## Настройки в зависимости -В некоторых случаях может быть полезно предоставлять настройки из зависимости, вместо того, чтобы иметь глобальный объект с `settings`, который используется везде. +В некоторых случаях может быть полезно предоставлять настройки из зависимости, вместо использования глобального объекта `settings`, который используется везде. -Это может быть особенно полезно во время тестирования, поскольку очень легко переопределить зависимость с вашими собственными настраиваемыми настройками. +Это может быть особенно полезно во время тестирования, так как очень легко переопределить зависимость вашими собственными настройками. ### Файл конфигурации -Из предыдущего примера, ваш файл `config.py` может выглядеть так: +Исходя из предыдущего примера, ваш файл `config.py` может выглядеть так: {* ../../docs_src/settings/app02/config.py hl[10] *} @@ -160,45 +160,45 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p /// tip | Совет -Мы обсудим `@lru_cache` немного позже. +Мы обсудим `@lru_cache` чуть позже. -Пока что вы можете предположить, что `get_settings()` — это обычная функция. +На данный момент можно считать, что `get_settings()` — это обычная функция. /// -И затем мы можем требовать его из функции обработчика *path operation* в качестве зависимости и использовать его везде, где это необходимо. +А затем мы можем потребовать его в *функции-обработчике пути* как зависимость и использовать ее в любом месте, где это необходимо. {* ../../docs_src/settings/app02_an_py39/main.py hl[17,19:21] *} ### Настройки и тестирование -Затем будет очень легко предоставить другой объект настроек во время тестирования, создав переопределение зависимости для `get_settings`: +Затем вам будет очень легко предоставить другой объект настроек во время тестирования, создав переопределение зависимости для `get_settings`: {* ../../docs_src/settings/app02/test_main.py hl[9:10,13,21] *} -В переопределении зависимости мы устанавливаем новое значение для `admin_email` при создании нового объекта `Settings`, а затем возвращаем этот новый объект. +В переопределении зависимости мы устанавливаем новое значение для `admin_email`, создавая новый объект `Settings`, а затем возвращаем этот новый объект. Затем мы можем протестировать, что он используется. ## Чтение файла `.env` -Если у вас много настроек, которые, возможно, часто меняются, может быть полезно поместить их в файл и затем считать их как переменные окружения. +Если у вас есть множество настроек, которые могут часто меняться, возможно, в разных окружениях, может быть полезно поместить их в файл и затем считывать их из него, как если бы они были переменными окружения. -Эта практика настолько распространена, что у нее есть название, эти переменные окружения обычно размещаются в файл `.env`, и файл называется "dotenv". +Эта практика достаточно распространена, чтобы у нее было название, эти переменные окружения обычно помещаются в файл `.env`, и этот файл называется "dotenv". /// tip | Совет -Файл, начинающийся с точки (`.`), является скрытым файлом в системах, подобных Unix, таких как Linux и macOS. +Файл, начинающийся с точки (`.`), является скрытым файлом в системах, похожих на Unix, таких как Linux и macOS. -Но на самом деле файл с настройками dotenv не обязательно должен иметь такое имя. +Но файл dotenv не обязательно должен иметь именно такое имя. /// -Pydantic поддерживает чтение из этих типов файлов с использованием внешней библиотеки. Вы можете узнать больше на Pydantic Settings: Dotenv (.env) support. +Pydantic поддерживает считывание из таких файлов с использованием внешней библиотеки. Вы можете узнать больше на Pydantic Settings: Поддержка Dotenv (.env). /// tip | Совет -Для этого нужно `pip install python-dotenv`. +Для этого необходимо выполнить `pip install python-dotenv`. /// @@ -213,7 +213,7 @@ APP_NAME="ChimichangApp" ### Чтение настроек из `.env` -А затем обновите ваш `config.py` с: +А затем обновить ваш `config.py` следующим образом: //// tab | Pydantic v2 @@ -221,7 +221,7 @@ APP_NAME="ChimichangApp" /// tip | Совет -Атрибут `model_config` используется только для конфигурации Pydantic. Вы можете прочитать больше на Pydantic: Concepts: Configuration. +Атрибут `model_config` используется только для настройки Pydantic. Вы можете прочитать больше на Pydantic: Концепции: Конфигурация. /// @@ -233,7 +233,7 @@ APP_NAME="ChimichangApp" /// tip | Совет -Класс `Config` используется только для конфигурации Pydantic. Вы можете прочитать больше на Pydantic Model Config. +Класс `Config` используется только для настройки Pydantic. Вы можете прочитать больше на Конфигурация Pydantic модели. /// @@ -241,44 +241,44 @@ APP_NAME="ChimichangApp" /// info | Информация -В версии Pydantic 1 настройка осуществлялась во внутреннем классе `Config`, в версии Pydantic 2 это делается в атрибуте `model_config`. Этот атрибут принимает `dict`, и чтобы получить автозаполнение и inline ошибки, вы можете импортировать и использовать `SettingsConfigDict` для определения этой `dict`. +В версии Pydantic 1 конфигурация осуществлялась во внутреннем классе `Config`, в версии Pydantic 2 это делается в атрибуте `model_config`. Этот атрибут принимает `dict`, и чтобы получить автозавершение и встроенные ошибки, вы можете импортировать и использовать `SettingsConfigDict` для определения этого `dict`. /// -Здесь мы определяем конфигурацию `env_file` внутри класса Pydantic `Settings` и устанавливаем значение на имя файла с файлом dotenv, который мы хотим использовать. +Здесь мы определяем конфигурацию `env_file` внутри вашего класса Pydantic `Settings` и устанавливаем значение для имени файла с файлом dotenv, который мы хотим использовать. -### Создание `Settings` только один раз с помощью `lru_cache` +### Создание `Settings` только один раз с `lru_cache` -Чтение файла с диска обычно является затратной (медленной) операцией, поэтому вы, вероятно, захотите делать это только один раз, а затем повторно использовать тот же объект настроек, вместо того, чтобы считывать его для каждого запроса. +Чтение файла с диска обычно является дорогой (медленной) операцией, поэтому, вероятно, вы захотите делать это только один раз, а затем использовать тот же объект настроек, вместо того чтобы считывать его для каждого запроса. -Но каждый раз, когда мы делаем: +Но каждый раз, когда мы выполняем: ```Python Settings() ``` -будет создаваться новый объект `Settings`, и при создании он будет снова читать файл `.env`. +новый объект `Settings` будет создан, и при создании он снова считает файл `.env`. -Если бы функция зависимости была следующей: +Если бы функция зависимости выглядела так: ```Python def get_settings(): return Settings() ``` -мы бы создавали этот объект для каждого запроса и читали бы файл `.env` для каждого запроса. ⚠️ +мы бы создавали этот объект для каждого запроса, и мы бы считывали файл `.env` для каждого запроса. ⚠️ -Но поскольку мы используем декоратор `@lru_cache` сверху, объект `Settings` будет создан только один раз, первый раз когда вызывается. ✔️ +Но так как мы используем декоратор `@lru_cache` сверху, объект `Settings` будет создан только один раз, при первом вызове. ✔️ {* ../../docs_src/settings/app03_an_py39/main.py hl[1,11] *} -Затем для любых последующих вызовов `get_settings()` в зависимостях для следующих запросов, вместо выполнения внутреннего кода `get_settings()` и создания нового объекта `Settings`, он будет возвращать тот же объект, который был возвращен при первом вызове, снова и снова. +Затем для всех последующих вызовов `get_settings()` в зависимостях для следующих запросов, вместо выполнения внутреннего кода функции `get_settings()` и создания нового объекта `Settings`, будет возвращен тот же объект, который был возвращен при первом вызове, снова и снова. -#### Технические подробности `lru_cache` +#### Технические детали `lru_cache` -`@lru_cache` модифицирует функцию, которую он декорирует, чтобы возвращать то же значение, которое было возвращено в первый раз, вместо того, чтобы вычислять его заново, выполняя код функции каждый раз. +`@lru_cache` модифицирует функцию, которую он декорирует, чтобы возвращать то же самое значение, которое было возвращено в первый раз, вместо того чтобы вычислять его снова, выполняя код функции каждый раз. -Таким образом, функция ниже будет выполняться один раз для каждой комбинации аргументов. А затем значения, возвращенные каждой из этих комбинаций аргументов, будут использоваться снова и снова, когда функция вызывается с точно такой же комбинацией аргументов. +Таким образом, функция ниже будет выполнена один раз для каждой комбинации аргументов. А затем возвращаемые значения для каждой из этих комбинаций аргументов будут использоваться снова и снова, когда функция вызывается с точно такой же комбинацией аргументов. Например, если у вас есть функция: @@ -288,59 +288,59 @@ def say_hi(name: str, salutation: str = "Ms."): return f"Hello {salutation} {name}" ``` -ваша программа может выполняться следующим образом: +ваша программа может выполняться так: ```mermaid sequenceDiagram -participant code as Code +participant code as Код participant function as say_hi() -participant execute as Execute function +participant execute as Выполнить код функции rect rgba(0, 255, 0, .1) code ->> function: say_hi(name="Camila") - function ->> execute: execute function code - execute ->> code: return the result + function ->> execute: выполнить код функции + execute ->> code: вернуть результат end rect rgba(0, 255, 255, .1) code ->> function: say_hi(name="Camila") - function ->> code: return stored result + function ->> code: вернуть сохраненный результат end rect rgba(0, 255, 0, .1) code ->> function: say_hi(name="Rick") - function ->> execute: execute function code - execute ->> code: return the result + function ->> execute: выполнить код функции + execute ->> code: вернуть результат end rect rgba(0, 255, 0, .1) code ->> function: say_hi(name="Rick", salutation="Mr.") - function ->> execute: execute function code - execute ->> code: return the result + function ->> execute: выполнить код функции + execute ->> code: вернуть результат end rect rgba(0, 255, 255, .1) code ->> function: say_hi(name="Rick") - function ->> code: return stored result + function ->> code: вернуть сохраненный результат end rect rgba(0, 255, 255, .1) code ->> function: say_hi(name="Camila") - function ->> code: return stored result + function ->> code: вернуть сохраненный результат end ``` -В случае нашей зависимости `get_settings()`, функция даже не принимает никаких аргументов, поэтому она всегда возвращает одно и то же значение. +В случае нашей зависимости `get_settings()`, функция даже не принимает никаких аргументов, поэтому всегда возвращает одно и то же значение. -Таким образом, она ведет себя почти так, как если бы это была просто глобальная переменная. Но поскольку она использует функцию-зависимость, мы можем легко переопределить ее для тестирования. +Таким образом, она ведет себя почти как глобальная переменная. Но поскольку используется функция зависимости, мы можем легко переопределить ее для тестирования. -`@lru_cache` является частью `functools`, который является частью стандартной библиотеки Python, вы можете прочитать больше об этом в документации Python для `@lru_cache`. +`@lru_cache` является частью `functools`, который является частью стандартной библиотеки Python, вы можете прочитать больше об этом в документации Python по `@lru_cache`. ## Резюме -Вы можете использовать Pydantic Settings для обработки настроек или конфигураций вашего приложения, с всей мощью моделей Pydantic. +Вы можете использовать Pydantic Settings для управления настройками или конфигурациями вашего приложения, используя все возможности Pydantic-моделей. -* С помощью зависимости вы можете упростить тестирование. -* Вы можете использовать `.env` файлы вместе с ним. -* Использование `@lru_cache` позволяет избежать повторного чтения dotenv файла для каждого запроса, при этом позволяя его переопределение во время тестирования. +* Используя зависимость, вы можете упростить тестирование. +* Вы можете использовать `.env` файлы с ним. +* Использование `@lru_cache` позволяет избежать повторного чтения файла dotenv для каждого запроса, при этом позволяя его переопределять во время тестирования. diff --git a/docs/ru/docs/advanced/sub-applications.md b/docs/ru/docs/advanced/sub-applications.md index 1e389f5eb..468c09155 100644 --- a/docs/ru/docs/advanced/sub-applications.md +++ b/docs/ru/docs/advanced/sub-applications.md @@ -1,36 +1,36 @@ -# Подприложения - Монтирование +# Подприложения - Mounts -Если вам нужно иметь два независимых приложения FastAPI, каждое со своей независимой OpenAPI и собственным интерфейсом документации, вы можете создать основное приложение и "монтировать" одно (или несколько) подпрограмм. +Если вам нужно иметь два независимых FastAPI приложения, каждое с собственным, независимым OpenAPI и собственными интерфейсами документации, вы можете создать основное приложение и "смонтировать" одно (или более) подприложение(я). -## Монтирование приложения **FastAPI** +## Монтирование **FastAPI** приложения -"Монтирование" означает добавление полностью "независимого" приложения в определенный путь, которое будет обрабатывать все запросы, поступающие по этому пути, с _operations path_, объявленными в этом подприложении. +"Монтирование" означает добавление полностью "независимого" приложения в определенный path, которое затем будет обрабатывать все под этим path, с _операциями пути_, объявленными в этом подприложении. -### Приложение верхнего уровня +### Высокоуровневое приложение -Сначала создайте главное приложение верхнего уровня **FastAPI** и его *operations path*: +Сначала создайте основное, высшего уровня, **FastAPI** приложение и его *операции пути*: {* ../../docs_src/sub_applications/tutorial001.py hl[3, 6:8] *} ### Подприложение -Затем создайте свое подприложение и его *operations path*. +Затем создайте ваше подприложение и его *операции пути*. -Это подприложение является просто еще одним стандартным приложением FastAPI, но именно оно будет "смонтировано": +Это подприложение является стандартным FastAPI приложением, но именно оно будет "смонтировано": {* ../../docs_src/sub_applications/tutorial001.py hl[11, 14:16] *} ### Монтирование подприложения -В вашем приложении верхнего уровня `app` смонтируйте подприложение `subapi`. +В вашем высшего уровня приложении, `app`, смонтируйте подприложение, `subapi`. -В этом случае оно будет смонтировано по пути `/subapi`: +В этом случае оно будет смонтировано на path `/subapi`: {* ../../docs_src/sub_applications/tutorial001.py hl[11, 19] *} -### Проверка автоматической документации API +### Проверьте автоматическую документацию API -Теперь выполните команду `fastapi` с вашим файлом: +Теперь запустите команду `fastapi` с вашим файлом:
@@ -44,24 +44,24 @@ $ fastapi dev main.py И откройте документацию по адресу http://127.0.0.1:8000/docs. -Вы увидите автоматическую документацию API для основного приложения, содержащую только его _operations path_: +Вы увидите автоматическую документацию API для основного приложения, включающую лишь его собственные _операции пути_: Затем откройте документацию для подприложения по адресу http://127.0.0.1:8000/subapi/docs. -Вы увидите автоматическую документацию API для подприложения, содержащую только его _operations path_, все с правильным префиксом подпути `/subapi`: +Вы увидите автоматическую документацию API для подприложения, включающую только его собственные _операции пути_, все с правильным префиксом под-path `/subapi`: -Если вы попробуете взаимодействовать с любым из этих двух пользовательских интерфейсов, они будут работать корректно, потому что браузер сможет общаться с каждым определенным приложением или подприложением. +Если вы попробуете взаимодействовать с любым из двух пользовательских интерфейсов, они будут работать правильно, потому что браузер сможет обратиться к каждому конкретному приложению или подприложению. ### Технические детали: `root_path` -Когда вы монтируете подприложение, как описано выше, FastAPI позаботится о передаче пути монтирования для подприложения с использованием механизма из спецификации ASGI, называемого `root_path`. +Когда вы монтируете подприложение, как описано выше, FastAPI позаботится о передаче пути монтирования для подприложения, используя механизм из спецификации ASGI, называемый `root_path`. -Таким образом, подприложение будет знать об использовании этого префикса пути для интерфейса документации. +Таким образом, подприложение будет знать, что необходимо использовать этот префикс пути для UI документации. -И подприложение также может иметь свои собственные смонтированные подприложения и все будет работать корректно, так как FastAPI автоматически обрабатывает все эти `root_path`. +И подприложение также может иметь свои собственные смонтированные подприложения, и всё будет работать корректно, потому что FastAPI обрабатывает все эти `root_path`s автоматически. -Вы узнаете больше о `root_path` и о том, как использовать его явно, в разделе о [работе за прокси](behind-a-proxy.md){.internal-link target=_blank}. +Вы узнаете больше о `root_path` и том, как его использовать явно в разделе про [Работу за прокси-сервером](behind-a-proxy.md){.internal-link target=_blank}. diff --git a/docs/ru/docs/advanced/templates.md b/docs/ru/docs/advanced/templates.md index bc7f498ea..06ed543b0 100644 --- a/docs/ru/docs/advanced/templates.md +++ b/docs/ru/docs/advanced/templates.md @@ -1,14 +1,14 @@ # Шаблоны -Вы можете использовать любой механизм шаблонов с **FastAPI**. +Вы можете использовать любой шаблонизатор, который захотите, с **FastAPI**. -Распространенным выбором является Jinja2, тот же, что используется в Flask и других инструментах. +Популярным выбором является Jinja2, который также используется Flask и другими инструментами. -Есть утилиты для легкой конфигурации, которые вы можете использовать непосредственно в вашем приложении **FastAPI** (предоставлено Starlette). +Существуют утилиты для его простой настройки, которые вы можете использовать непосредственно в своем приложении **FastAPI** (предоставлено Starlette). ## Установка зависимостей -Убедитесь, что вы создаете [виртуальное окружение](../virtual-environments.md){.internal-link target=_blank}, активируйте его и установите `jinja2`: +Убедитесь, что вы создали [виртуальное окружение](../virtual-environments.md){.internal-link target=_blank}, активировали его и установили `jinja2`:
@@ -23,43 +23,43 @@ $ pip install jinja2 ## Использование `Jinja2Templates` * Импортируйте `Jinja2Templates`. -* Создайте объект `templates`, который можно будет использовать позже. -* Объявите параметр `Request` в *операции маршрута*, который будет возвращать шаблон. -* Используйте созданные вами `templates`, чтобы рендерить и возвращать `TemplateResponse`, передавая имя шаблона, объект запроса и "контекст" — словарь с парами ключ-значение, которые будут использоваться внутри шаблона Jinja2. +* Создайте объект `templates`, который вы сможете повторно использовать позднее. +* Объявите параметр `Request` в *операции пути*, которая будет возвращать шаблон. +* Используйте созданные вами `templates` для рендеринга и возврата `TemplateResponse`, передайте имя шаблона, объект запроса и словарь "context" с парами "ключ-значение", которые будут использоваться внутри шаблона Jinja2. {* ../../docs_src/templates/tutorial001.py hl[4,11,15:18] *} /// note | Примечание -До версии FastAPI 0.108.0 и Starlette 0.29.0 первым параметром был `name`. +До FastAPI 0.108.0, Starlette 0.29.0, параметр `name` был первым. -Также до этого, в предыдущих версиях, объект `request` передавался как часть пар ключ-значение в контексте для Jinja2. +Также, до этого, в предыдущих версиях объект `request` передавался как часть пар ключ-значение в контексте для Jinja2. /// /// tip | Совет -Объявляя `response_class=HTMLResponse`, интерфейс документов сможет знать, что ответ будет в формате HTML. +Объявляя `response_class=HTMLResponse`, интерфейс документации сможет определить, что ответ будет в формате HTML. /// -/// note | Технические подробности +/// note | Технические детали Вы также можете использовать `from starlette.templating import Jinja2Templates`. -**FastAPI** предоставляет ту же `starlette.templating` под именем `fastapi.templating` просто для вашего удобства, разработчика. Но большинство доступных ответов напрямую из Starlette. То же самое с `Request` и `StaticFiles`. +**FastAPI** предоставляет тот же `starlette.templating` как `fastapi.templating` просто для вашего удобства, разработчик. Но большинство доступных ответов поступают непосредственно от Starlette. То же самое касается `Request` и `StaticFiles`. /// ## Написание шаблонов -Затем вы можете написать шаблон в `templates/item.html` с, например: +Затем вы можете написать шаблон в `templates/item.html`, например: ```jinja hl_lines="7" {!../../docs_src/templates/templates/item.html!} ``` -### Контекстные значения шаблона +### Значения контекста шаблона В HTML, который содержит: @@ -71,13 +71,13 @@ Item ID: {{ id }} {% endraw %} -...это отобразит `id`, взятый из "контекста" `dict`, который вы передали: +...будет показан `id`, взятый из "context" `dict`, который вы передали: ```Python {"id": id} ``` -Например, с ID `42`, это отобразится как: +Например, с `id`, равным `42`, это будет рендериться как: ```html Item ID: 42 @@ -85,9 +85,9 @@ Item ID: 42 ### Аргументы `url_for` в шаблоне -Вы также можете использовать `url_for()` внутри шаблона, он принимает в качестве аргументов те же аргументы, которые будут использованы вашей *функцией операции маршрута*. +Вы также можете использовать `url_for()` внутри шаблона; он принимает в качестве аргументов те же аргументы, которые использовались бы в вашей *функции-обработчике пути*. -Таким образом, секция с: +Таким образом, раздел с: {% raw %} @@ -97,23 +97,23 @@ Item ID: 42 {% endraw %} -...создаст ссылку на тот же URL, который будет обрабатываться *функцией операции маршрута* `read_item(id=id)`. +...сгенерирует ссылку на тот же URL, который был бы обработан *функцией-обработчиком пути* `read_item(id=id)`. -Например, с ID `42`, это отобразится как: +Например, с `id`, равным `42`, это будет рендериться как: ```html ``` -## Шаблоны и статичные файлы +## Шаблоны и статические файлы -Вы также можете использовать `url_for()` внутри шаблона, и использовать его, например, с `StaticFiles`, которые вы закрепили с `name="static"`. +Вы также можете использовать `url_for()` внутри шаблона и использовать его, например, с `StaticFiles`, которые вы смонтировали с `name="static"`. ```jinja hl_lines="4" {!../../docs_src/templates/templates/item.html!} ``` -В этом примере это бы связало с файлом CSS в `static/styles.css` с: +В этом примере это будет ссылка на CSS-файл по пути `static/styles.css` с: ```CSS hl_lines="4" {!../../docs_src/templates/static/styles.css!} @@ -121,6 +121,6 @@ Item ID: 42 И поскольку вы используете `StaticFiles`, этот CSS-файл будет автоматически обслуживаться вашим приложением **FastAPI** по URL `/static/styles.css`. -## Подробнее +## Дополнительные сведения -Для получения более подробной информации, включая тестирование шаблонов, посетите документацию Starlette по шаблонам. +Для получения дополнительной информации, включая тестирование шаблонов, смотрите документацию Starlette по шаблонам. diff --git a/docs/ru/docs/advanced/testing-dependencies.md b/docs/ru/docs/advanced/testing-dependencies.md index 2554156a9..b48c89e8d 100644 --- a/docs/ru/docs/advanced/testing-dependencies.md +++ b/docs/ru/docs/advanced/testing-dependencies.md @@ -1,46 +1,46 @@ -# Тестирование зависимостей с переопределением +# Тестирование зависимостей с использованием переопределений -## Переопределение зависимостей во время тестирования +## Переопределение зависимостей в процессе тестирования -Существуют сценарии, когда вы можете захотеть переопределить зависимость во время тестирования. +Существуют сценарии, когда вам может понадобиться переопределить зависимость во время тестирования. -Вы не хотите, чтобы изначальная зависимость запускалась (а также любые ее подзависимости). +Вы не хотите, чтобы оригинальная зависимость выполнялась (также как и любые её подзависимости). -Вместо этого вы хотите предоставить другую зависимость, которая будет использоваться только во время тестов (возможно, только для некоторых конкретных тестов) и будет предоставлять значение, которое можно использовать там, где использовалось значение первоначальной зависимости. +Вместо этого, вы хотите предоставить другую зависимость, которая будет использоваться только во время тестов (возможно, только для некоторых конкретных тестов), и будет предоставлять значение, которое можно использовать там, где использовалось значение оригинальной зависимости. ### Примеры использования: внешний сервис -Примером может быть наличие внешнего поставщика аутентификации, которого вам нужно вызывать. +Примером может служить ситуация, когда у вас есть внешний провайдер аутентификации, которого вам необходимо вызывать. Вы отправляете ему токен, и он возвращает аутентифицированного пользователя. -Этот поставщик может взимать плату за каждый запрос, и его вызов может занимать больше времени, чем если бы вы использовали заранее заданного пользователя-симулятора для тестов. +Этот провайдер может брать плату за каждый запрос, и вызов его может занять больше времени, чем если бы вы использовали фиксированного пользователя-мока для тестов. -Вы, вероятно, захотите протестировать внешнего поставщика один раз, но не обязательно вызывать его для каждого выполняемого теста. +Вероятно, вы захотите протестировать внешнего провайдера один раз, но не обязательно вызывать его для каждого теста, который вы запускаете. -В этом случае вы можете переопределить зависимость, которая вызывает этого поставщика, и использовать пользовательскую зависимость, которая возвращает пользователя-симулятора, только для ваших тестов. +В этом случае вы можете переопределить зависимость, которая вызывает этого провайдера, и использовать пользовательскую зависимость, которая возвращает мока-пользователя, только для ваших тестов. ### Использование атрибута `app.dependency_overrides` -Для таких случаев ваше приложение **FastAPI** имеет атрибут `app.dependency_overrides`, который представляет собой простой `dict`. +В таких случаях ваше приложение **FastAPI** имеет атрибут `app.dependency_overrides`, который является простым `dict`. -Чтобы переопределить зависимость для тестирования, вы используете в качестве ключа оригинальную зависимость (функцию), а в качестве значения — функцию-переопределение вашей зависимости. +Чтобы переопределить зависимость для тестирования, вы указываете оригинальную зависимость (функцию) в качестве ключа, и ваше переопределение зависимости (другую функцию) в качестве значения. -Затем **FastAPI** вызовет это переопределение вместо оригинальной зависимости. +Затем **FastAPI** будет вызывать это переопределение вместо оригинальной зависимости. {* ../../docs_src/dependency_testing/tutorial001_an_py310.py hl[26:27,30] *} /// tip | Совет -Вы можете задать переопределение зависимости для зависимости, используемой где угодно в вашем приложении **FastAPI**. +Вы можете установить переопределение зависимости для зависимости, используемой в любом месте вашего приложения **FastAPI**. -Изначальная зависимость может использоваться в *функции операции пути*, *декораторе операции пути* (когда вы не используете возвращаемое значение), вызове `.include_router()` и т. д. +Оригинальная зависимость может использоваться в *функции-обработчике пути*, *декораторе операции пути* (если вы не используете возвращаемое значение), вызове `.include_router()`, и т. д. -FastAPI все равно сможет переопределить ее. +FastAPI все равно сможет ее переопределить. /// -Затем вы можете сбросить свои переопределения (удалить их), установив `app.dependency_overrides` в пустой `dict`: +Затем вы можете сбросить ваши переопределения (удалить их), установив `app.dependency_overrides` в пустой `dict`: ```Python app.dependency_overrides = {} @@ -48,6 +48,6 @@ app.dependency_overrides = {} /// tip | Совет -Если вы хотите переопределить зависимость только во время некоторых тестов, вы можете установить переопределение в начале теста (внутри функции теста) и сбросить его в конце (в конце функции теста). +Если вы хотите переопределить зависимость только в некоторых тестах, вы можете установить переопределение в начале теста (внутри тестовой функции) и сбросить его в конце (в конце тестовой функции). /// diff --git a/docs/ru/docs/advanced/testing-events.md b/docs/ru/docs/advanced/testing-events.md index 398c2e829..12a33f7f6 100644 --- a/docs/ru/docs/advanced/testing-events.md +++ b/docs/ru/docs/advanced/testing-events.md @@ -1,5 +1,5 @@ -# Тестирование событий: запуск - завершение +# Тестирование событий: startup - shutdown -Когда вам нужно, чтобы ваши обработчики событий (`startup` и `shutdown`) запускались в тестах, вы можете использовать `TestClient` вместе с оператором `with`: +Когда вам нужно, чтобы ваши обработчики событий (`startup` и `shutdown`) запускались в ваших тестах, вы можете использовать `TestClient` с оператором `with`: {* ../../docs_src/app_testing/tutorial003.py hl[9:12,20:24] *} diff --git a/docs/ru/docs/advanced/testing-websockets.md b/docs/ru/docs/advanced/testing-websockets.md index 59564ac94..8dd898a4f 100644 --- a/docs/ru/docs/advanced/testing-websockets.md +++ b/docs/ru/docs/advanced/testing-websockets.md @@ -2,12 +2,12 @@ Вы можете использовать тот же `TestClient` для тестирования WebSockets. -Для этого вы используете `TestClient` в `with`-заявлении, подключаясь к WebSocket: +Для этого вы используете `TestClient` в операторе `with`, подключаясь к WebSocket: {* ../../docs_src/app_testing/tutorial002.py hl[27:31] *} -/// note | Примечание +/// note | Заметка -Для получения более подробной информации ознакомьтесь с документацией Starlette по тестированию WebSockets. +Для получения дополнительных сведений обратитесь к документации Starlette для тестирования WebSockets. /// diff --git a/docs/ru/docs/advanced/using-request-directly.md b/docs/ru/docs/advanced/using-request-directly.md index de9e4768d..ca81a4b0f 100644 --- a/docs/ru/docs/advanced/using-request-directly.md +++ b/docs/ru/docs/advanced/using-request-directly.md @@ -1,56 +1,56 @@ -# Использование объекта Request напрямую +# Прямое использование объекта Request -До сих пор вы объявляли части запроса, которые вам нужны, с указанием их типов. +До сих пор вы объявляли части HTTP-запроса, которые вам нужны, с указанием их типов. Получение данных из: -* Параметров пути. -* Заголовков. -* Куки. +* path как параметров. +* HTTP-заголовков. +* cookies. * и т.д. -И при этом **FastAPI** проверяет эти данные, конвертирует их и автоматически генерирует документацию для вашего API. +И благодаря этому, **FastAPI** валидирует эти данные, выполняет их преобразование и автоматически генерирует документацию для вашего API. -Но бывают ситуации, когда может понадобиться доступ к объекту `Request` напрямую. +Но есть ситуации, когда может понадобиться доступ к объекту `Request` напрямую. ## Подробности об объекте `Request` -Так как **FastAPI** на самом деле является **Starlette** под капотом, с рядом различных инструментов поверх, вы можете использовать объект `Request` от Starlette напрямую, когда это необходимо. +Так как **FastAPI** на самом деле построен на **Starlette**, с уровнем дополнительных инструментов сверху, вы можете использовать объект `Request` из Starlette напрямую, когда это необходимо. -Это также означает, что если вы получаете данные из объекта `Request` напрямую (например, читаете тело запроса), они не будут проверены, конвертированы или задокументированы (с помощью OpenAPI, для автоматического интерфейса пользователя API) FastAPI. +Это также означает, что если вы получаете данные из объекта `Request` напрямую (например, читаете тело запроса), они не будут валидироваться, преобразовываться или документироваться (с использованием OpenAPI для автоматического пользовательского интерфейса API) в FastAPI. -Хотя любой другой параметр, объявленный обычным образом (например, тело с моделью Pydantic), будет проверяться, конвертироваться, аннотироваться и так далее. +Хотя любой другой параметр, объявленный обычно (например, тело запроса с Pydantic моделью), все равно будет валидироваться, преобразовываться, аннотироваться и т.д. -Но есть конкретные случаи, когда полезно получить объект `Request`. +Но есть определенные случаи, когда полезно получить объект `Request`. -## Используйте объект `Request` напрямую +## Использование объекта `Request` напрямую -Представьте, что вы хотите получить IP-адрес/хост клиента внутри вашей *функции операции пути*. +Представьте, что вы хотите получить IP-адрес/хост клиента внутри вашей *функции-обработчика пути*. -Для этого вам нужно получить доступ к запросу напрямую. +Для этого вам нужно будет получить доступ к запросу напрямую. {* ../../docs_src/using_request_directly/tutorial001.py hl[1,7:8] *} -Объявив параметр *функции операции пути* с типом `Request`, **FastAPI** поймет, что нужно передать `Request` в этот параметр. +Объявляя параметр *функции-обработчика пути* с типом `Request`, **FastAPI** поймет, что необходимо передать объект `Request` в этот параметр. -/// tip | Совет +/// tip | Подсказка -Обратите внимание, что в этом случае мы объявляем параметр пути рядом с параметром запроса. +Обратите внимание, что в этом случае мы объявляем path параметр вместе с параметром запроса. -Таким образом, параметр пути будет извлечен, проверен, преобразован в указанный тип и аннотирован с OpenAPI. +Таким образом, path параметр будет извлечен, провалидирован, преобразован в указанный тип и аннотирован с помощью OpenAPI. -Аналогично, вы можете объявить любой другой параметр обычным образом, и дополнительно получить объект `Request` тоже. +Точно так же вы можете объявить любой другой параметр как обычно, и дополнительно получить также объект `Request`. /// -## Документация `Request` +## Документация по `Request` -Вы можете прочитать больше подробностей об объекте `Request` на официальном сайте документации Starlette. +Вы можете прочитать больше деталей о объекте `Request` на официальном сайте документации Starlette. -/// note | Технические подробности +/// note | Технические Подробности Вы также можете использовать `from starlette.requests import Request`. -**FastAPI** предоставляет это напрямую просто как удобство для вас, разработчика. Но оно поступает напрямую от Starlette. +**FastAPI** предоставляет это напрямую просто для удобства для вас, разработчика. Но эта функция приходит прямо из Starlette. /// diff --git a/docs/ru/docs/advanced/wsgi.md b/docs/ru/docs/advanced/wsgi.md index 7e3f5c840..519ae8e51 100644 --- a/docs/ru/docs/advanced/wsgi.md +++ b/docs/ru/docs/advanced/wsgi.md @@ -1,32 +1,32 @@ -# Включение WSGI - Flask, Django, другие +# Включение WSGI - Flask, Django и другие -Вы можете монтировать WSGI-приложения, как вы видели в [Sub Applications - Mounts](sub-applications.md){.internal-link target=_blank}, [Behind a Proxy](behind-a-proxy.md){.internal-link target=_blank}. +Вы можете монтировать WSGI-приложения, как вы видели в разделе [Дополнительные приложения - Монтирования](sub-applications.md){.internal-link target=_blank}, [За прокси](behind-a-proxy.md){.internal-link target=_blank}. -Для этого вы можете использовать `WSGIMiddleware` и использовать его для обёртки вашего WSGI-приложения, например, Flask, Django и т. д. +Для этого вы можете использовать `WSGIMiddleware`, чтобы обернуть ваше WSGI-приложение, например, Flask, Django и т.д. ## Использование `WSGIMiddleware` Вам нужно импортировать `WSGIMiddleware`. -Затем оберните WSGI (например, Flask) приложение с помощью middleware. +Затем обернуть WSGI (например, Flask) приложение с помощью middleware (промежуточного слоя). -И затем смонтируйте его под определённым путём. +И затем смонтировать это под path. {* ../../docs_src/wsgi/tutorial001.py hl[2:3,3] *} -## Проверка +## Проверьте это -Теперь каждый запрос по пути `/v1/` будет обрабатываться приложением Flask. +Теперь каждый HTTP-запрос по path `/v1/` будет обработан приложением Flask. -А остальные будут обрабатываться **FastAPI**. +А остальные запросы будут обработаны **FastAPI**. -Если вы запустите его и перейдёте на http://localhost:8000/v1/, вы увидите ответ от Flask: +Если вы запустите его и перейдете по ссылке http://localhost:8000/v1/, вы увидите ответ от Flask: ```txt Hello, World from Flask! ``` -А если вы перейдёте на http://localhost:8000/v2, вы увидите ответ от FastAPI: +И если вы перейдете по ссылке http://localhost:8000/v2, вы увидите ответ от FastAPI: ```JSON { diff --git a/docs/ru/docs/deployment/cloud.md b/docs/ru/docs/deployment/cloud.md index 2a6f62d66..fd523146f 100644 --- a/docs/ru/docs/deployment/cloud.md +++ b/docs/ru/docs/deployment/cloud.md @@ -1,6 +1,6 @@ -# Развертывание FastAPI на облачных платформах +# Развёртывание FastAPI на облачных провайдерах -Вы можете использовать практически **любого облачного провайдера** для развертывания вашего приложения на FastAPI. +Вы можете использовать практически **любого облачного провайдера** для развертывания вашего приложения FastAPI. В большинстве случаев у основных облачных провайдеров есть руководства по развертыванию FastAPI с их помощью. @@ -8,9 +8,9 @@ Некоторые облачные провайдеры ✨ [**спонсируют FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, это обеспечивает продолжительное и здоровое **развитие** FastAPI и его **экосистемы**. -И это демонстрирует их искреннюю приверженность FastAPI и его **сообществу** (вам), так как они не только хотят предоставить вам **хороший сервис**, но и убедиться, что у вас есть **хорошая и здоровая платформа**, FastAPI. 🙇 +Это демонстрирует их настоящую приверженность FastAPI и его **сообществу** (вам), так как они не только хотят предоставить вам **хороший сервис**, но и хотят убедиться, что у вас есть **хороший и здоровый фреймворк**, FastAPI. 🙇 -Возможно, вы захотите попробовать их услуги и следовать их руководствам: +Возможно, вам захочется попробовать их услуги и следовать их руководствам: * Platform.sh * Porter diff --git a/docs/ru/docs/deployment/server-workers.md b/docs/ru/docs/deployment/server-workers.md index b12b20b8d..1551b00d5 100644 --- a/docs/ru/docs/deployment/server-workers.md +++ b/docs/ru/docs/deployment/server-workers.md @@ -1,33 +1,33 @@ -# Серверные Рабочие Процессы - Uvicorn с Рабочими Процессами +# Воркеры сервера - Uvicorn с воркерами -Давайте вспомним те концепции развёртывания, которые мы обсуждали ранее: +Давайте снова рассмотрим концепции деплоя: * Безопасность - HTTPS * Запуск при старте * Перезапуски -* **Репликация (количество запущенных процессов)** +* **Репликация (количество рабочих процессов)** * Память -* Предыдущие шаги перед запуском +* Подготовительные шаги перед запуском -До этого момента, с помощью всех руководств в документации, вы, вероятно, запускали **серверную программу**, например, используя команду `fastapi`, которая запускает Uvicorn, выполняющую **один процесс**. +До этого момента, с помощью всех туториалов в документации, вы, вероятно, запускали **серверную программу**, например, используя команду `fastapi`, которая запускает Uvicorn, выполняя **единственный процесс**. -При развертывании приложений, вероятно, вы захотите иметь **репликацию процессов**, чтобы воспользоваться преимуществами **множества ядер** и быть способными обрабатывать больше запросов. +При деплое приложений вы, вероятно, захотите иметь некоторую **репликацию процессов**, чтобы воспользоваться преимуществами **многих ядер** и иметь возможность обрабатывать больше запросов. -Как вы узнали в предыдущей главе о [Концепции Развёртывания](concepts.md){.internal-link target=_blank}, существует множество стратегий, которые можно использовать. +Как вы видели в предыдущей главе о [Концепции деплоя](concepts.md){.internal-link target=_blank}, существует множество стратегий, которые вы можете использовать. -Здесь я покажу вам, как использовать **Uvicorn** с **рабочими процессами**, используя команду `fastapi` или напрямую команду `uvicorn`. +Здесь я покажу вам, как использовать **Uvicorn** с **воркер-процессами**, используя команду `fastapi` или непосредственно команду `uvicorn`. /// info | Информация -Если вы используете контейнеры, например с Docker или Kubernetes, я расскажу вам больше об этом в следующей главе: [FastAPI в Контейнерах - Docker](docker.md){.internal-link target=_blank}. +Если вы используете контейнеры, например, с Docker или Kubernetes, я расскажу вам больше об этом в следующей главе: [FastAPI в контейнерах - Docker](docker.md){.internal-link target=_blank}. -Особенно при запуске на **Kubernetes** вы, вероятно, **не захотите** использовать рабочих процессы и вместо этого запускать **один процесс Uvicorn на контейнер**, но я расскажу вам о этом позже в той главе. +В частности, работая с **Kubernetes**, вы, вероятно, **не** захотите использовать воркеры, а вместо этого запускать **один процесс Uvicorn в контейнере**, но об этом я расскажу позже в той главе. /// -## Несколько Рабочих Процессов +## Несколько воркеров -Вы можете запустить несколько рабочих процессов с помощью опции командной строки `--workers`: +Вы можете запустить несколько воркеров, используя опцию командной строки `--workers`: //// tab | `fastapi` @@ -38,41 +38,39 @@ ```console $ fastapi run --workers 4 main.py - FastAPI Запуск производственного сервера 🚀 + FastAPI Запуск продакшн-сервера 🚀 Поиск структуры файлов пакета в директориях с - __init__.py файлами + __init__.py Импорт из /home/user/code/awesomeapp module 🐍 main.py - code Импорт объекта приложения FastAPI из модуля с - следующим кодом: + code Импортирование объекта приложения FastAPI из модуля со следующим кодом: from main import app - app Используется строка импорта: main:app + app Использование строки импорта: main:app - server Сервер запущен на http://0.0.0.0:8000 - server Документация на http://0.0.0.0:8000/docs + server Сервер стартовал на http://0.0.0.0:8000 + server Документация по адресу http://0.0.0.0:8000/docs Логи: - INFO Uvicorn работает на http://0.0.0.0:8000 (Нажмите CTRL+C для - выхода) - INFO Запущен родительский процесс [27365] - INFO Запущен процесс сервера [27368] - INFO Запущен процесс сервера [27369] - INFO Запущен процесс сервера [27370] - INFO Запущен процесс сервера [27367] + INFO Uvicorn работает на http://0.0.0.0:8000 (Нажмите CTRL+C для выхода) + INFO Стартовал родительский процесс [27365] + INFO Стартовал серверный процесс [27368] + INFO Стартовал серверный процесс [27369] + INFO Стартовал серверный процесс [27370] + INFO Стартовал серверный процесс [27367] INFO Ожидание запуска приложения. INFO Ожидание запуска приложения. INFO Ожидание запуска приложения. INFO Ожидание запуска приложения. - INFO Запуск приложения завершен. - INFO Запуск приложения завершен. - INFO Запуск приложения завершен. - INFO Запуск приложения завершен. + INFO Запуск приложения завершён. + INFO Запуск приложения завершён. + INFO Запуск приложения завершён. + INFO Запуск приложения завершён. ```
@@ -88,52 +86,52 @@ $ fastapi run --workers 4 INFO: Uvicorn работает на http://0.0.0.0:8080 (Нажмите CTRL+C для выхода) -INFO: Запущен родительский процесс [27365] -INFO: Запущен процесс сервера [27368] +INFO: Стартовал родительский процесс [27365] +INFO: Стартовал серверный процесс [27368] INFO: Ожидание запуска приложения. -INFO: Запуск приложения завершен. -INFO: Запущен процесс сервера [27369] +INFO: Запуск приложения завершён. +INFO: Стартовал серверный процесс [27369] INFO: Ожидание запуска приложения. -INFO: Запуск приложения завершен. -INFO: Запущен процесс сервера [27370] +INFO: Запуск приложения завершён. +INFO: Стартовал серверный процесс [27370] INFO: Ожидание запуска приложения. -INFO: Запуск приложения завершен. -INFO: Запущен процесс сервера [27367] +INFO: Запуск приложения завершён. +INFO: Стартовал серверный процесс [27367] INFO: Ожидание запуска приложения. -INFO: Запуск приложения завершен. +INFO: Запуск приложения завершён. ```
//// -Единственный новый параметр здесь - это `--workers`, который говорит Uvicorn запустить 4 рабочих процесса. +Единственная новая опция здесь - `--workers`, указывающая Uvicorn запустить 4 воркер-процесса. -Вы также можете видеть, что он показывает **PID** каждого процесса, `27365` для родительского процесса (это **менеджер процессов**) и один для каждого рабочего процесса: `27368`, `27369`, `27370` и `27367`. +Вы также можете увидеть, что отображается **PID** каждого процесса: `27365` для родительского процесса (это **менеджер процессов**) и один для каждого воркер-процесса: `27368`, `27369`, `27370` и `27367`. -## Концепции Развёртывания +## Концепции деплоя -Здесь вы увидели, как использовать несколько **рабочих процессов** для **параллелизации** выполнения приложения, использования преимуществ **нескольких ядер** процессора и возможности обслуживать **больше запросов**. +Здесь вы увидели, как использовать несколько **воркеров** для **параллелизации** выполнения приложения, использовать преимущества **многих ядер** процессора и иметь возможность обрабатывать **больше запросов**. -Из списка концепций развёртывания, используя рабочие процессы, вы в основном поможете с частью **репликации** и немного с **перезапусками**, но вы все равно должны позаботиться о других: +Из списка концепций деплоя, приведённого выше, использование воркеров в основном поможет с **репликацией**, и немного - с **перезапусками**, но вам по-прежнему необходимо позаботиться о следующих вещах: * **Безопасность - HTTPS** * **Запуск при старте** * ***Перезапуски*** -* Репликация (количество запущенных процессов) +* Репликация (количество рабочих процессов) * **Память** -* **Предыдущие шаги перед запуском** +* **Подготовительные шаги перед запуском** ## Контейнеры и Docker -В следующей главе о [FastAPI в Контейнерах - Docker](docker.md){.internal-link target=_blank} я объясню некоторые стратегии, которые вы могли бы использовать для обработки других **концепций развёртывания**. +В следующей главе о [FastAPI в контейнерах - Docker](docker.md){.internal-link target=_blank} я объясню некоторые стратегии, которые вы можете использовать для работы с другими **концепциями деплоя**. -Я покажу вам, как **создать свое собственное изображение с нуля**, чтобы запустить единый Uvicorn процесс. Это простой процесс и, вероятно, то, что вы захотите сделать, когда используете распределенную систему управления контейнерами, такую как **Kubernetes**. +Я покажу вам, как **создать собственный образ с нуля** для запуска одного процесса Uvicorn. Это простой процесс и, вероятно, то, что вы захотите сделать при использовании системы управления распределёнными контейнерами, такой как **Kubernetes**. -## Итоги +## Итог -Вы можете использовать несколько рабочих процессов с помощью опции CLI `--workers` с командами `fastapi` или `uvicorn`, чтобы воспользоваться преимуществами **многоядерных процессоров**, для параллельного выполнения **нескольких процессов**. +Вы можете использовать несколько воркер-процессов с опцией `--workers` в CLI с командами `fastapi` или `uvicorn`, чтобы воспользоваться преимуществами **многоядерных процессоров**, для выполнения **нескольких процессов параллельно**. -Вы могли бы использовать эти инструменты и идеи, если вы настраиваете **свою собственную систему развёртывания**, при этом самостоятельно заботясь о других концепциях развёртывания. +Вы можете использовать эти инструменты и идеи, если настраиваете **собственную систему деплоя**, одновременно заботясь о других концепциях деплоя самостоятельно. -Ознакомьтесь с следующей главой, чтобы узнать о **FastAPI** с контейнерами (например, Docker и Kubernetes). Вы увидите, что у этих инструментов есть простые способы решения других **концепций развёртывания**. ✨ +Изучите следующую главу, чтобы узнать о **FastAPI** с контейнерами (например, Docker и Kubernetes). Вы увидите, что эти инструменты также имеют простые способы решения других **концепций деплоя**. ✨ diff --git a/docs/ru/docs/how-to/conditional-openapi.md b/docs/ru/docs/how-to/conditional-openapi.md index a0ce1525d..2ade71806 100644 --- a/docs/ru/docs/how-to/conditional-openapi.md +++ b/docs/ru/docs/how-to/conditional-openapi.md @@ -1,31 +1,31 @@ # Условный OpenAPI -Если это необходимо, вы можете использовать настройки и переменные окружения для условной конфигурации OpenAPI в зависимости от среды и даже полностью его отключить. +Если потребуется, вы можете использовать настройки и переменные окружения, чтобы условно настраивать OpenAPI в зависимости от окружения, и даже полностью отключать его. ## О безопасности, API и документации -Сокрытие пользовательских интерфейсов вашей документации в продакшене *не должно* быть способом защиты вашего API. +Скрытие пользовательских интерфейсов вашей документации в продакшне *не должно* быть способом защиты вашего API. -Это не добавляет никакой дополнительной безопасности вашему API, *операции с путями* по-прежнему будут доступны там, где они находятся. +Это не добавляет никакой дополнительной безопасности вашему API, *операции пути* по-прежнему будут доступны там, где они есть. -Если в вашем коде есть уязвимость, она все равно будет существовать. +Если в вашем коде есть уязвимость, она всё равно будет существовать. -Сокрытие документации просто усложняет понимание того, как взаимодействовать с вашим API, и может усложнить отладку в продакшене. Это можно считать просто формой безопасности через неясность. +Скрытие документации лишь затрудняет понимание того, как взаимодействовать с вашим API, и может усложнить его отладку в продакшне. Это может рассматриваться просто как форма безопасности через неясность. -Если вы хотите обезопасить ваш API, есть несколько более эффективных методов, например: +Если вы хотите защитить ваш API, есть несколько более эффективных подходов: -* Убедитесь, что у вас есть правильно определенные Pydantic модели для тел запросов и ответов. -* Настройте необходимые разрешения и роли с помощью зависимостей. -* Никогда не храните пароли в открытом виде, только хэши паролей. -* Реализуйте и используйте хорошо известные криптографические инструменты, такие как Passlib и JWT токены и т. д. -* Добавьте более гранулированное управление разрешениями с помощью OAuth2 скоупов там, где это необходимо. +* Убедитесь, что у вас есть хорошо определённые Pydantic-модели для тел запросов и ответов. +* Настройте необходимые разрешения и роли с использованием зависимостей. +* Никогда не храните пароли в открытом виде, только хеши паролей. +* Реализуйте и используйте известные криптографические инструменты, такие как Passlib и JWT токены и т. д. +* Добавьте более детальный контроль разрешений с помощью OAuth2 областей, где это необходимо. * ...и так далее. -Тем не менее, у вас может быть очень специфичный случай, когда вам действительно нужно отключить документацию API для какой-то среды (например, для продакшена) или в зависимости от конфигураций из переменных окружения. +Тем не менее, может быть очень специфический случай, когда вам действительно нужно отключить документацию API для какого-то окружения (например, для продакшна) или в зависимости от настроек из переменных окружения. ## Условный OpenAPI из настроек и переменных окружения -Вы можете легко использовать те же настройки Pydantic для конфигурации вашего сгенерированного OpenAPI и пользовательских интерфейсов документации. +Вы можете легко использовать те же настройки Pydantic для конфигурации вашего сгенерированного OpenAPI и интерфейсов документации. Например: @@ -33,9 +33,9 @@ Здесь мы объявляем настройку `openapi_url` с тем же значением по умолчанию `"/openapi.json"`. -Затем мы используем её при создании приложения `FastAPI`. +Затем мы используем его при создании приложения `FastAPI`. -Затем вы можете отключить OpenAPI (включая UI документацию), установив переменную окружения `OPENAPI_URL` в пустую строку, например: +Затем вы можете отключить OpenAPI (включая документацию UI) путем установки значения переменной окружения `OPENAPI_URL` в пустую строку, так:
@@ -47,7 +47,7 @@ $ OPENAPI_URL= uvicorn main:app
-Затем, если вы перейдете по URL на `/openapi.json`, `/docs` или `/redoc`, вы получите ошибку `404 Not Found`, например: +Затем, если вы перейдете по URL-адресам `/openapi.json`, `/docs` или `/redoc`, вы получите ошибку `404 Not Found`, например: ```JSON { diff --git a/docs/ru/docs/how-to/configure-swagger-ui.md b/docs/ru/docs/how-to/configure-swagger-ui.md index 5cced2c04..d8822b1b1 100644 --- a/docs/ru/docs/how-to/configure-swagger-ui.md +++ b/docs/ru/docs/how-to/configure-swagger-ui.md @@ -4,9 +4,9 @@ Чтобы их настроить, передайте аргумент `swagger_ui_parameters` при создании объекта приложения `FastAPI()` или в функцию `get_swagger_ui_html()`. -`swagger_ui_parameters` принимает словарь с конфигурациями, переданными напрямую в Swagger UI. +`swagger_ui_parameters` принимает словарь с конфигурациями, передаваемыми непосредственно в Swagger UI. -FastAPI конвертирует конфигурации в **JSON**, чтобы сделать их совместимыми с JavaScript, так как именно это необходимо для Swagger UI. +FastAPI преобразует конфигурации в **JSON**, чтобы они были совместимы с JavaScript, так как это нужно для Swagger UI. ## Отключение подсветки синтаксиса @@ -20,13 +20,13 @@ FastAPI конвертирует конфигурации в **JSON**, чтоб {* ../../docs_src/configure_swagger_ui/tutorial001.py hl[3] *} -... и тогда Swagger UI больше не будет показывать подсветку синтаксиса: +...и тогда Swagger UI больше не будет отображать подсветку синтаксиса: ## Изменение темы -Таким же образом вы можете задать тему подсветки синтаксиса с помощью ключа `"syntaxHighlight.theme"` (обратите внимание, что в нём есть точка посередине): +Таким же образом вы можете установить тему подсветки синтаксиса с помощью ключа `"syntaxHighlight.theme"` (обратите внимание, что в нем есть точка): {* ../../docs_src/configure_swagger_ui/tutorial002.py hl[3] *} @@ -38,7 +38,7 @@ FastAPI конвертирует конфигурации в **JSON**, чтоб FastAPI включает некоторые параметры конфигурации по умолчанию, подходящие для большинства случаев использования. -Она включает в себя эти параметры по умолчанию: +Эти конфигурации по умолчанию включают: {* ../../fastapi/openapi/docs.py ln[8:23] hl[17:23] *} @@ -50,13 +50,13 @@ FastAPI включает некоторые параметры конфигур ## Другие параметры Swagger UI -Чтобы увидеть все возможные конфигурации, которые вы можете использовать, прочтите официальную документацию о параметрах Swagger UI. +Чтобы узнать о всех возможных конфигурациях, которые вы можете использовать, прочитайте официальную документацию по параметрам Swagger UI. ## Настройки только для JavaScript -Swagger UI также позволяет настроить другие параметры как объекты **только для JavaScript** (например, функции JavaScript). +Swagger UI также позволяет использовать другие конфигурации, представляющие собой **только для JavaScript** объекты (например, функции JavaScript). -FastAPI также включает эти настройки `presets` только для JavaScript: +FastAPI также включает эти настройки `presets`, предназначенные только для JavaScript: ```JavaScript presets: [ @@ -65,6 +65,6 @@ presets: [ ] ``` -Это объекты **JavaScript**, а не строки, поэтому вы не можете передавать их напрямую из Python-кода. +Это объекты **JavaScript**, а не строки, поэтому вы не можете передавать их напрямую из кода Python. -Если вам нужно использовать конфигурации только для JavaScript, как эти, вы можете использовать один из методов, упомянутых выше. Переопределите всю *path operation* Swagger UI и вручную напишите любой необходимый JavaScript. +Если вам нужно использовать такие настройки, предназначенные только для JavaScript, вы можете использовать один из методов выше. Переопределите все *операции пути* Swagger UI и вручную напишите любой нужный JavaScript. diff --git a/docs/ru/docs/how-to/custom-docs-ui-assets.md b/docs/ru/docs/how-to/custom-docs-ui-assets.md index 853af9626..8887cc57a 100644 --- a/docs/ru/docs/how-to/custom-docs-ui-assets.md +++ b/docs/ru/docs/how-to/custom-docs-ui-assets.md @@ -1,36 +1,36 @@ -# Пользовательские статические ресурсы Docs UI (самостоятельный хостинг) +# Статические ресурсы пользовательского интерфейса для документации (самостоятельный хостинг) -API документация использует **Swagger UI** и **ReDoc**, и каждому из них требуются некоторые файлы JavaScript и CSS. +Документация API использует **Swagger UI** и **ReDoc**, и для каждой из них нужны определенные JavaScript и CSS файлы. -По умолчанию эти файлы предоставляются через CDN. +По умолчанию эти файлы обслуживаются с CDN. -Но возможно его настроить: можно установить определенный CDN или разместить файлы самостоятельно. +Но можно настроить их по-своему, задать определенный CDN или обслуживать файлы самостоятельно. ## Пользовательский CDN для JavaScript и CSS -Предположим, что вы хотите использовать другой CDN, например, хотите использовать `https://unpkg.com/`. +Допустим, вы хотите использовать другой CDN, например, `https://unpkg.com/`. -Это может быть полезно, если, например, вы живете в стране, где некоторые URL-адреса ограничены. +Это может быть полезно, если, например, вы живете в стране, где ограничивают некоторые URL-адреса. -### Отключение автоматической документации +### Отключите автоматическую документацию -Первый шаг — отключить автоматическую документацию, так как по умолчанию они используют стандартный CDN. +Первый шаг — отключить автоматическую документацию, так как по умолчанию она использует стандартный CDN. -Чтобы отключить их, установите их URL в `None` при создании вашего приложения `FastAPI`: +Чтобы отключить их, установите для их URL-адресов значение `None` при создании приложения `FastAPI`: {* ../../docs_src/custom_docs_ui/tutorial001.py hl[8] *} -### Включение пользовательской документации +### Включите пользовательскую документацию -Теперь вы можете создать *path operations* для пользовательской документации. +Теперь вы можете создать *операции пути* для пользовательской документации. -Вы можете повторно использовать внутренние функции FastAPI для создания HTML-страниц документации и передавать им необходимые аргументы: +Вы можете повторно использовать внутренние функции FastAPI для создания HTML-страниц для документации и передать им необходимые аргументы: -* `openapi_url`: URL-адрес, по которому HTML-страница документации может получить схему OpenAPI вашего API. Здесь можно использовать атрибут `app.openapi_url`. +* `openapi_url`: URL-адрес, где HTML-страница документации может получить OpenAPI-схему для вашего API. Вы можете использовать здесь атрибут `app.openapi_url`. * `title`: заголовок вашего API. -* `oauth2_redirect_url`: здесь можно использовать `app.swagger_ui_oauth2_redirect_url`, чтобы использовать стандартный. -* `swagger_js_url`: URL-адрес, по которому HTML вашей документации на Swagger UI может получить файл **JavaScript**. Это пользовательский URL-адрес CDN. -* `swagger_css_url`: URL-адрес, по которому HTML вашей документации на Swagger UI может получить файл **CSS**. Это пользовательский URL-адрес CDN. +* `oauth2_redirect_url`: здесь вы можете использовать `app.swagger_ui_oauth2_redirect_url`, чтобы воспользоваться значением по умолчанию. +* `swagger_js_url`: URL-адрес, по которому HTML для ваших документов Swagger UI может получить **JavaScript** файл. Это пользовательский URL-адрес CDN. +* `swagger_css_url`: URL-адрес, по которому HTML для ваших документов Swagger UI может получить **CSS** файл. Это пользовательский URL-адрес CDN. И аналогично для ReDoc... @@ -38,33 +38,33 @@ API документация использует **Swagger UI** и **ReDoc**, /// tip | Совет -*Path operation* для `swagger_ui_redirect` является помощником, когда вы используете OAuth2. +*Операция пути* для `swagger_ui_redirect` — это вспомогательная функция, когда вы используете OAuth2. -Если вы интегрируете свой API с провайдером OAuth2, вы сможете авторизоваться и вернуться к документации API с полученными учетными данными. И взаимодействовать с ним, используя реальную аутентификацию через OAuth2. +Если вы интегрируете свой API с провайдером OAuth2, вы сможете пройти аутентификацию и вернуться к документации API с полученными учетными данными. И взаимодействовать с ней, используя настоящую аутентификацию OAuth2. -Swagger UI сделает это для вас за кулисами, но для этого нужен этот помощник "перенаправления". +Swagger UI справится с этим закулисно для вас, но ему нужен этот вспомогательный "редирект". /// -### Создание *path operation* для его тестирования +### Создайте *операцию пути* для тестирования -Теперь, чтобы проверить, что все работает, создайте *path operation*: +Теперь, чтобы убедиться, что всё работает, создайте *операцию пути*: {* ../../docs_src/custom_docs_ui/tutorial001.py hl[36:38] *} -### Тестирование +### Проверьте это -Теперь вы должны иметь возможность перейти на свою документацию по адресу http://127.0.0.1:8000/docs и перезагрузить страницу, она загрузит эти ресурсы с нового CDN. +Теперь вы должны иметь возможность перейти к вашей документации по адресу http://127.0.0.1:8000/docs и перезагрузить страницу. Она будет загружать эти ресурсы с нового CDN. ## Самостоятельный хостинг JavaScript и CSS для документации -Самостоятельный хостинг JavaScript и CSS может быть полезен, если, например, вам нужно, чтобы ваше приложение продолжало работать даже в автономном режиме, без доступа в интернет или в локальной сети. +Самостоятельный хостинг JavaScript и CSS может быть полезен, если, например, вам нужно, чтобы ваше приложение продолжало работать даже в офлайн-режиме, без открытого доступа к Интернету, или в локальной сети. -Здесь вы увидите, как самостоятельно размещать эти файлы в том же приложении FastAPI и настраивать документацию для их использования. +Здесь вы увидите, как можно обслуживать эти файлы самостоятельно, в том же приложении FastAPI, и настроить документацию для их использования. ### Структура файлов проекта -Допустим, ваша структура файлов проекта выглядит следующим образом: +Допустим, структура файлов вашего проекта выглядит так: ``` . @@ -75,7 +75,7 @@ Swagger UI сделает это для вас за кулисами, но дл Теперь создайте каталог для хранения этих статических файлов. -Ваша новая структура файлов может выглядеть так: +Теперь ваша новая структура файлов может выглядеть так: ``` . @@ -85,9 +85,9 @@ Swagger UI сделает это для вас за кулисами, но дл └── static/ ``` -### Загрузка файлов +### Загрузите файлы -Скачайте необходимые для документации статические файлы и поместите их в каталог `static/`. +Загрузите необходимые статические файлы для документации и разместите их в каталоге `static/`. Вы можете щелкнуть правой кнопкой мыши по каждой ссылке и выбрать опцию, аналогичную `Сохранить ссылку как...`. @@ -100,7 +100,7 @@ Swagger UI сделает это для вас за кулисами, но дл * `redoc.standalone.js` -После этого ваша структура файлов может выглядеть так: +После этого ваша структура файлов может выглядеть следующим образом: ``` . @@ -116,47 +116,47 @@ Swagger UI сделает это для вас за кулисами, но дл ### Обслуживание статических файлов * Импортируйте `StaticFiles`. -* "Подключите" экземпляр `StaticFiles()` в определенном пути. +* "Монтируйте" экземпляр `StaticFiles()` на конкретном пути. {* ../../docs_src/custom_docs_ui/tutorial002.py hl[7,11] *} ### Тестирование статических файлов -Запустите приложение и перейдите по адресу http://127.0.0.1:8000/static/redoc.standalone.js. +Запустите ваше приложение и перейдите на http://127.0.0.1:8000/static/redoc.standalone.js. Вы должны увидеть очень длинный JavaScript файл для **ReDoc**. Он может начинаться с чего-то вроде: ```JavaScript -/*! For license information please see redoc.standalone.js.LICENSE.txt */ +/*! Для информации о лицензии смотрите redoc.standalone.js.LICENSE.txt */ !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")): ... ``` -Это подтверждает, что вы можете обслуживать статические файлы из вашего приложения и что вы разместили статические файлы для документации в правильном месте. +Это подтверждает, что вы можете обслуживать статические файлы из вашего приложения, и что вы разместили статические файлы для документации в правильном месте. -Теперь мы можем настроить приложение для использования этих статических файлов в документации. +Теперь мы можем настроить приложение для использования этих статических файлов для документации. -### Отключение автоматической документации для статических файлов +### Отключите автоматическую документацию для статических файлов -Как и при использовании пользовательского CDN, первым шагом является отключение автоматической документации, так как по умолчанию они используют CDN. +Также как при использовании пользовательского CDN, первый шаг — отключить автоматическую документацию, так как по умолчанию они используют CDN. -Чтобы отключить их, установите их URL в `None` при создании вашего приложения `FastAPI`: +Чтобы отключить их, установите для их URL-адресов значение `None` при создании приложения `FastAPI`: {* ../../docs_src/custom_docs_ui/tutorial002.py hl[9] *} -### Включение пользовательской документации для статических файлов +### Включите пользовательскую документацию для статических файлов -И так же, как с пользовательским CDN, теперь вы можете создать *path operations* для пользовательской документации. +И аналогично предыдущим шагам с пользовательским CDN, теперь вы можете создать *операции пути* для пользовательской документации. -Снова можно использовать внутренние функции FastAPI для создания HTML-страниц документации и передавать им необходимые аргументы: +Опять же, вы можете повторно использовать внутренние функции FastAPI для создания HTML-страниц для документации и передать им необходимые аргументы: -* `openapi_url`: URL-адрес, по которому HTML-страница документации может получить схему OpenAPI вашего API. Здесь можно использовать атрибут `app.openapi_url`. +* `openapi_url`: URL-адрес, где HTML-страница документации может получить OpenAPI-схему для вашего API. Вы можете использовать здесь атрибут `app.openapi_url`. * `title`: заголовок вашего API. -* `oauth2_redirect_url`: здесь можно использовать `app.swagger_ui_oauth2_redirect_url`, чтобы использовать стандартный. -* `swagger_js_url`: URL-адрес, по которому HTML вашей документации на Swagger UI может получить файл **JavaScript**. **Это файл, который ваше приложение теперь обслуживает**. -* `swagger_css_url`: URL-адрес, по которому HTML вашей документации на Swagger UI может получить файл **CSS**. **Это файл, который ваше приложение теперь обслуживает**. +* `oauth2_redirect_url`: здесь вы можете использовать `app.swagger_ui_oauth2_redirect_url`, чтобы воспользоваться значением по умолчанию. +* `swagger_js_url`: URL-адрес, по которому HTML для ваших документов Swagger UI может получить **JavaScript** файл. **Это тот файл, который теперь обслуживает ваше приложение**. +* `swagger_css_url`: URL-адрес, по которому HTML для ваших документов Swagger UI может получить **CSS** файл. **Это тот файл, который теперь обслуживает ваше приложение**. И аналогично для ReDoc... @@ -164,22 +164,22 @@ Swagger UI сделает это для вас за кулисами, но дл /// tip | Совет -*Path operation* для `swagger_ui_redirect` является помощником, когда вы используете OAuth2. +*Операция пути* для `swagger_ui_redirect` — это вспомогательная функция, когда вы используете OAuth2. -Если вы интегрируете свой API с провайдером OAuth2, вы сможете авторизоваться и вернуться к документации API с полученными учетными данными. И взаимодействовать с ним, используя реальную аутентификацию через OAuth2. +Если вы интегрируете свой API с провайдером OAuth2, вы сможете пройти аутентификацию и вернуться к документации API с полученными учетными данными. И взаимодействовать с ней, используя настоящую аутентификацию OAuth2. -Swagger UI сделает это для вас за кулисами, но для этого нужен этот помощник "перенаправления". +Swagger UI справится с этим закулисно для вас, но ему нужен этот вспомогательный "редирект". /// -### Создание *path operation* для тестирования статических файлов +### Создайте *операцию пути* для тестирования статических файлов -Теперь, чтобы убедиться, что все работает, создайте *path operation*: +Теперь, чтобы убедиться, что всё работает, создайте *операцию пути*: {* ../../docs_src/custom_docs_ui/tutorial002.py hl[39:41] *} -### Тестирование статических файлов UI +### Проверьте пользовательский интерфейс статических файлов -Теперь вы должны иметь возможность отключить Wi-Fi, перейти на свою документацию по адресу http://127.0.0.1:8000/docs и перезагрузить страницу. +Теперь вы должны иметь возможность отключить WiFi, перейти к вашей документации по адресу http://127.0.0.1:8000/docs и перезагрузить страницу. -И даже без Интернета вы сможете увидеть документацию вашего API и взаимодействовать с ней. +И даже без Интернета вы сможете увидеть документацию для вашего API и взаимодействовать с ней. diff --git a/docs/ru/docs/how-to/custom-request-and-route.md b/docs/ru/docs/how-to/custom-request-and-route.md index 62c13dd4e..8ade9cf73 100644 --- a/docs/ru/docs/how-to/custom-request-and-route.md +++ b/docs/ru/docs/how-to/custom-request-and-route.md @@ -1,109 +1,109 @@ -# Классы кастомных запросов и APIRoute +# Пользовательские классы Request и APIRoute -В некоторых случаях вы можете захотеть переопределить логику, используемую классами `Request` и `APIRoute`. +В некоторых случаях вам может понадобиться переопределить логику, используемую в классах `Request` и `APIRoute`. -В частности, это может быть хорошей альтернативой логике в middleware. +В частности, это может быть хорошей альтернативой логике в middleware (Промежуточный слой). -Например, если вы хотите прочитать или изменить тело запроса до его обработки вашим приложением. +Например, если вы хотите прочитать или изменить тело запроса до того, как оно будет обработано вашим приложением. -/// danger | Опасность +/// danger Это "продвинутая" функция. -Если вы только начинаете с **FastAPI**, возможно, вам стоит пропустить этот раздел. +Если вы только начинаете работать с **FastAPI**, вы можете пропустить этот раздел. /// -## Примеры использования +## Сценарии использования -Некоторые примеры использования включают: +Некоторые сценарии использования включают: -* Конвертацию тел запросов, которые не являются JSON, в JSON (например, `msgpack`). -* Распаковку тел запросов, сжатых с помощью gzip. +* Конвертация тел запросов, не являющихся JSON, в JSON (например, `msgpack`). +* Разжатие тел запросов, сжатых методом gzip. * Автоматическое логирование всех тел запросов. -## Обработка кастомных кодировок тел запросов +## Обработка пользовательских кодировок тела запроса -Давайте рассмотрим, как использовать подкласс `Request` для распаковки запросов в формате gzip. +Давайте посмотрим, как использовать пользовательский подкласс `Request` для разжатия gzip-запросов. -И подкласс `APIRoute` для использования этого кастомного класса запроса. +И подкласс `APIRoute`, чтобы использовать этот пользовательский класс запроса. -### Создание кастомного класса `GzipRequest` +### Создание пользовательского класса `GzipRequest` -/// tip | Подсказка +/// tip | Совет -Это учебный пример, демонстрирующий, как это работает; если вам нужна поддержка Gzip, вы можете использовать предоставленный [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware){.internal-link target=_blank}. +Это учебный пример, чтобы показать как это работает. Если вам нужна поддержка gzip, вы можете использовать предоставленный [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware){.internal-link target=_blank}. /// -Сначала мы создаем класс `GzipRequest`, который будет переопределять метод `Request.body()` для распаковки тела при наличии соответствующего заголовка. +Сначала мы создадим класс `GzipRequest`, который переопределит метод `Request.body()`, чтобы разжать тело запроса, если присутствует соответствующий заголовок. -Если в заголовке нет `gzip`, он не будет пытаться распаковать тело. +Если в заголовке нет `gzip`, он не будет пытаться разжать тело запроса. -Таким образом, один и тот же класс маршрута может обрабатывать как сжатые, так и несжатые запросы в формате gzip. +Таким образом, один и тот же класс маршрута может обрабатывать как gzip-сжатые, так и несжатые запросы. {* ../../docs_src/custom_request_and_route/tutorial001.py hl[8:15] *} -### Создание кастомного класса `GzipRoute` +### Создание пользовательского класса `GzipRoute` -Далее, мы создаем кастомный подкласс `fastapi.routing.APIRoute`, который будет использовать `GzipRequest`. +Затем мы создаем пользовательский подкласс `fastapi.routing.APIRoute`, который будет использовать `GzipRequest`. На этот раз он переопределит метод `APIRoute.get_route_handler()`. -Этот метод возвращает функцию. И именно эта функция принимает запрос и возвращает ответ. +Этот метод возвращает функцию. И эта функция принимает запрос и возвращает ответ. -Здесь мы используем его для создания `GzipRequest` из оригинального запроса. +Здесь мы используем его для создания `GzipRequest` из исходного запроса. {* ../../docs_src/custom_request_and_route/tutorial001.py hl[18:26] *} /// note | Технические детали -`Request` имеет атрибут `request.scope`, это просто Python `dict`, содержащий метаданные, связанные с запросом. +`Request` имеет атрибут `request.scope`, который является просто Python-словарем, содержащим метаданные, относящиеся к запросу. `Request` также имеет `request.receive`, это функция для "получения" тела запроса. -`scope` `dict` и функция `receive` обе являются частью спецификации ASGI. +Словарь `scope` и функция `receive` являются частью спецификации ASGI. -И эти две вещи, `scope` и `receive`, — то, что нужно для создания нового экземпляра `Request`. +И именно эти две вещи, `scope` и `receive`, нужны для создания нового экземпляра `Request`. Чтобы узнать больше о `Request`, ознакомьтесь с документацией Starlette о запросах. /// -Единственное, что функция, возвращаемая `GzipRequest.get_route_handler`, делает иначе — это преобразует `Request` в `GzipRequest`. +Единственное, что функция, возвращаемая `GzipRequest.get_route_handler`, делает иначе, это преобразует `Request` в `GzipRequest`. -Делая это, наш `GzipRequest` позаботится о распаковке данных (если это необходимо) до передачи их нашим *операциям на пути*. +Таким образом, наш `GzipRequest` позаботится о разжатии данных (если это необходимо) перед передачей их нашим *операциям пути*. -После этого вся логика обработки остается той же. +После этого вся логика обработки такая же. -Но из-за наших изменений в `GzipRequest.body`, тело запроса будет автоматически распаковано, когда оно понадобится **FastAPI**. +Но благодаря изменениям в `GzipRequest.body`, тело запроса будет автоматически разжиматься, когда **FastAPI** нужно будет его загрузить. ## Доступ к телу запроса в обработчике исключений /// tip | Подсказка -Для решения этой же проблемы, вероятно, гораздо проще использовать `body` в кастомном обработчике для `RequestValidationError` ([Обработка ошибок](../tutorial/handling-errors.md#use-the-requestvalidationerror-body){.internal-link target=_blank}). +Чтобы решить эту же проблему, вероятно, гораздо проще использовать `body` в пользовательском обработчике для `RequestValidationError` ([Обработка ошибок](../tutorial/handling-errors.md#use-the-requestvalidationerror-body){.internal-link target=_blank}). -Но этот пример все же действителен и показывает, как взаимодействовать с внутренними компонентами. +Но этот пример по-прежнему актуален и показывает, как взаимодействовать с внутренними компонентами. /// -Мы также можем использовать этот же подход для доступа к телу запроса в обработчике исключений. +Мы также можем использовать этот же подход, чтобы получить доступ к телу запроса в обработчике исключений. -Все, что нам нужно сделать, это обработать запрос внутри блока `try`/`except`: +Все, что нам нужно сделать, — это обработать запрос внутри блока `try`/`except`: {* ../../docs_src/custom_request_and_route/tutorial002.py hl[13,15] *} -Если произойдет исключение, экземпляр `Request` все равно будет в доступной области, так что мы сможем прочитать и использовать тело запроса при обработке ошибки: +Если возникает исключение, экземпляр `Request` все равно будет доступен, поэтому мы можем прочитать и использовать тело запроса при обработке ошибки: {* ../../docs_src/custom_request_and_route/tutorial002.py hl[16:18] *} -## Кастомный класс `APIRoute` в маршрутизаторе +## Пользовательский класс `APIRoute` в роутере Вы также можете установить параметр `route_class` для `APIRouter`: {* ../../docs_src/custom_request_and_route/tutorial003.py hl[26] *} -В этом примере операции пути под `router` будут использовать кастомный класс `TimedRoute` и добавят в ответ заголовок `X-Response-Time` с временем, затраченным на генерацию ответа: +В этом примере *операции путей* под `router` будут использовать пользовательский класс `TimedRoute`, и в ответе будет добавлен дополнительный HTTP-заголовок `X-Response-Time` с временем, затраченным на генерацию ответа: {* ../../docs_src/custom_request_and_route/tutorial003.py hl[13:20] *} diff --git a/docs/ru/docs/how-to/extending-openapi.md b/docs/ru/docs/how-to/extending-openapi.md index afa4479d4..d79ef0fdc 100644 --- a/docs/ru/docs/how-to/extending-openapi.md +++ b/docs/ru/docs/how-to/extending-openapi.md @@ -1,47 +1,47 @@ # Расширение OpenAPI -Есть случаи, когда вам может понадобиться изменить сгенерированную схему OpenAPI. +Бывают случаи, когда вам может понадобиться изменить сгенерированную схему OpenAPI. -В этом разделе вы увидите, как это сделать. +В этом разделе вы узнаете, как это сделать. ## Обычный процесс -Обычный (по умолчанию) процесс таков: +Обычный (по умолчанию) процесс выглядит следующим образом. -`FastAPI` приложение (экземпляр) имеет метод `.openapi()`, который должен возвращать схему OpenAPI. +Приложение `FastAPI` (экземпляр) имеет метод `.openapi()`, который ожидается вернуть схему OpenAPI. -В процессе создания объекта приложения регистрируется *операция пути* для `/openapi.json` (или для того, что вы установили в `openapi_url`). +В рамках создания объекта приложения для `/openapi.json` (или для того, что вы указали в `openapi_url`) регистрируется *операция пути*. -Он просто возвращает JSON-ответ с результатом выполнения метода `.openapi()` приложения. +Она просто возвращает JSON ответ с результатом метода `.openapi()` приложения. -По умолчанию, метод `.openapi()` проверяет свойство `.openapi_schema`, чтобы увидеть, есть ли в нем содержимое, и возвращает его. +По умолчанию метод `.openapi()` проверяет свойство `.openapi_schema`, чтобы увидеть, есть ли в нем содержимое, и возвращает их. -Если его нет, он генерирует его с использованием вспомогательной функции из `fastapi.openapi.utils.get_openapi`. +Если его нет, он генерирует его с использованием вспомогательной функции в `fastapi.openapi.utils.get_openapi`. -Эта функция `get_openapi()` принимает в качестве параметров: +И эта функция `get_openapi()` принимает в качестве параметров: -* `title`: Заголовок OpenAPI, показываемый в документации. -* `version`: Версия вашего API, например, `2.5.0`. -* `openapi_version`: Версия спецификации OpenAPI, используемая по умолчанию. На данный момент последняя версия: `3.1.0`. +* `title`: Заголовок OpenAPI, отображаемый в документации. +* `version`: Версия вашего API, например `2.5.0`. +* `openapi_version`: Версия спецификации OpenAPI, используемой. По умолчанию последняя: `3.1.0`. * `summary`: Краткое резюме API. -* `description`: Описание вашего API, которое может включать markdown и будет показано в документации. -* `routes`: Список маршрутов, каждое из них является зарегистрированной *операцией пути*. Они взяты из `app.routes`. +* `description`: Описание вашего API, оно может включать markdown и будет показано в документации. +* `routes`: Список маршрутов, это каждая из зарегистрированных *операций пути*. Они берутся из `app.routes`. /// info | Информация -Параметр `summary` доступен в OpenAPI 3.1.0 и выше, поддерживается в FastAPI 0.99.0 и выше. +Параметр `summary` доступен в OpenAPI 3.1.0 и выше, поддерживается FastAPI 0.99.0 и выше. /// -## Переопределение стандартных значений +## Переопределение значений по умолчанию -Используя вышеуказанную информацию, вы можете использовать ту же вспомогательную функцию для генерации схемы OpenAPI и переопределить каждую часть, которая вам нужна. +Используя информацию выше, вы можете использовать ту же вспомогательную функцию для генерации схемы OpenAPI и переопределения каждой части, которая вам нужна. -Например, давайте добавим расширение OpenAPI от ReDoc, чтобы включить нестандартный логотип. +Например, давайте добавим OpenAPI расширение ReDoc для включения настраиваемого логотипа. ### Обычный **FastAPI** -Сначала напишите все ваше приложение **FastAPI** как обычно: +Сначала напишите все ваше приложение на **FastAPI** как обычно: {* ../../docs_src/extending_openapi/tutorial001.py hl[1,4,7:9] *} @@ -53,17 +53,17 @@ ### Изменение схемы OpenAPI -Теперь вы можете добавить расширение ReDoc, добавив настраиваемый `x-logo` в "объект" `info` схемы OpenAPI: +Теперь вы можете добавить расширение ReDoc, добавив настраиваемый `x-logo` в "объект" `info` в схеме OpenAPI: {* ../../docs_src/extending_openapi/tutorial001.py hl[22:24] *} ### Кэширование схемы OpenAPI -Вы можете использовать свойство `.openapi_schema` в качестве "кэша" для хранения вашей сгенерированной схемы. +Вы можете использовать свойство `.openapi_schema` как "кэш", чтобы сохранить вашу сгенерированную схему. -Таким образом, вашему приложению не придется генерировать схему каждый раз, когда пользователь открывает вашу документацию API. +Таким образом, ваше приложение не будет генерировать схему каждый раз, когда пользователь открывает вашу документацию API. -Она будет сгенерирована только один раз, и затем будет использоваться та же закэшированная схема для следующих запросов. +Она будет сгенерирована только один раз, и затем та же самая кэшированная схема будет использована для следующих запросов. {* ../../docs_src/extending_openapi/tutorial001.py hl[13:14,25:26] *} @@ -73,8 +73,8 @@ {* ../../docs_src/extending_openapi/tutorial001.py hl[29] *} -### Проверка +### Проверьте это -Как только вы перейдете на http://127.0.0.1:8000/redoc, вы увидите, что используете свой нестандартный логотип (в этом примере, логотип **FastAPI**): +Как только вы перейдете по адресу http://127.0.0.1:8000/redoc, вы увидите, что вы используете ваш настраиваемый логотип (в этом примере используется логотип **FastAPI**): diff --git a/docs/ru/docs/how-to/general.md b/docs/ru/docs/how-to/general.md index 8add3a029..2372fbd74 100644 --- a/docs/ru/docs/how-to/general.md +++ b/docs/ru/docs/how-to/general.md @@ -1,39 +1,39 @@ -# Общие - Как сделать - Рецепты +# Общие сведения - How To - Рецепты -Вот несколько указателей на другие места в документации для общих или частых вопросов. +Вот несколько путеводителей на другие части документации для общих или часто задаваемых вопросов. ## Фильтрация данных - Безопасность -Чтобы убедиться, что вы не возвращаете больше данных, чем следует, прочитайте документацию [Учебник - Модель ответа - Возвращаемый тип](../tutorial/response-model.md){.internal-link target=_blank}. +Чтобы убедиться, что вы не возвращаете больше данных, чем следует, прочитайте документацию по [Учебнику - Модель ответа - Возвращаемый тип](../tutorial/response-model.md){.internal-link target=_blank}. ## Теги документации - OpenAPI -Чтобы добавить теги к вашим *операциям путей* и сгруппировать их в интерфейсе документации, прочитайте документацию [Учебник - Конфигурация операций пути - Теги](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank}. +Чтобы добавить теги к вашим *операциям пути* и сгруппировать их в интерфейсе документации, прочитайте документацию по [Учебнику - Конфигурации операций пути - Теги](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank}. -## Обзор и описание документации - OpenAPI +## Краткое описание и описание документации - OpenAPI -Чтобы добавить обзор и описание к вашим *операциям путей* и показать их в интерфейсе документации, прочитайте документацию [Учебник - Конфигурация операций пути - Обзор и описание](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank}. +Чтобы добавить краткое описание и описание к вашим *операциям пути* и отобразить их в интерфейсе документации, прочитайте документацию по [Учебнику - Конфигурации операций пути - Краткое описание и описание](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank}. ## Описание ответа в документации - OpenAPI -Чтобы определить описание ответа, показанное в интерфейсе документации, прочитайте документацию [Учебник - Конфигурация операций пути - Описание ответа](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank}. +Чтобы определить описание ответа, отображаемого в интерфейсе документации, прочитайте документацию по [Учебнику - Конфигурации операций пути - Описание ответа](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank}. -## Устаревание документации *Операций пути* - OpenAPI +## Устаревание *операции пути* в документации - OpenAPI -Чтобы объявить устаревание *операции пути* и показать это в интерфейсе документации, прочитайте документацию [Учебник - Конфигурация операций пути - Устаревание](../tutorial/path-operation-configuration.md#deprecate-a-path-operation){.internal-link target=_blank}. +Чтобы пометить *операцию пути* как устаревшую и отобразить это в интерфейсе документации, прочитайте документацию по [Учебнику - Конфигурации операций пути - Устаревание](../tutorial/path-operation-configuration.md#deprecate-a-path-operation){.internal-link target=_blank}. -## Конвертация любых данных в совместимые с JSON +## Преобразование любых данных в совместимые с JSON -Чтобы конвертировать любые данные в совместимые с JSON, прочитайте документацию [Учебник - Кодировщик, совместимый с JSON](../tutorial/encoder.md){.internal-link target=_blank}. +Чтобы преобразовать любые данные в совместимые с JSON, прочитайте документацию по [Учебнику - Совместимый кодировщик JSON](../tutorial/encoder.md){.internal-link target=_blank}. -## OpenAPI Метаданные - Документация +## Метаданные OpenAPI - Документация -Чтобы добавить метаданные к вашей OpenAPI схеме, включая лицензию, версию, контактные данные и т.д., прочитайте документацию [Учебник - Метаданные и URL-адреса документации](../tutorial/metadata.md){.internal-link target=_blank}. +Чтобы добавить метаданные в вашу схему OpenAPI, включая лицензию, версию, контактную информацию и т.д., прочитайте документацию по [Учебнику - Метаданные и URL-адреса документации](../tutorial/metadata.md){.internal-link target=_blank}. -## Настройка URL-адреса OpenAPI +## Пользовательский URL OpenAPI -Чтобы настроить (или удалить) URL-адрес OpenAPI, прочитайте документацию [Учебник - Метаданные и URL-адреса документации](../tutorial/metadata.md#openapi-url){.internal-link target=_blank}. +Чтобы кастомизировать (или удалить) URL OpenAPI, прочитайте документацию по [Учебнику - Метаданные и URL-адреса документации](../tutorial/metadata.md#openapi-url){.internal-link target=_blank}. ## URL-адреса документации OpenAPI -Чтобы обновить URL-адреса, используемые для автоматически сгенерированных пользовательских интерфейсов документации, прочитайте документацию [Учебник - Метаданные и URL-адреса документации](../tutorial/metadata.md#docs-urls){.internal-link target=_blank}. +Чтобы обновить URL-адреса, используемые для автоматически сгенерированных интерфейсов документации, прочитайте документацию по [Учебнику - Метаданные и URL-адреса документации](../tutorial/metadata.md#docs-urls){.internal-link target=_blank}. diff --git a/docs/ru/docs/how-to/graphql.md b/docs/ru/docs/how-to/graphql.md index 7ef1753c8..5c7fc1c5d 100644 --- a/docs/ru/docs/how-to/graphql.md +++ b/docs/ru/docs/how-to/graphql.md @@ -1,16 +1,16 @@ # GraphQL -Так как **FastAPI** основан на стандарте **ASGI**, интегрировать любую библиотеку **GraphQL**, совместимую с ASGI, очень просто. +Так как **FastAPI** основан на стандарте **ASGI**, очень легко интегрировать любую библиотеку **GraphQL**, также совместимую с ASGI. -Вы можете комбинировать обычные *маршруты* FastAPI с GraphQL в одном приложении. +Вы можете комбинировать обычные *операции пути* FastAPI с GraphQL в одном и том же приложении. /// tip | Совет -**GraphQL** решает некоторые очень специфичные случаи использования. +**GraphQL** решает некоторые очень специфические случаи использования. -Он имеет **преимущества** и **недостатки** по сравнению с обычными **веб API**. +У него есть **преимущества** и **недостатки** по сравнению с обычными **веб API**. -Убедитесь, что вы оценили, компенсируют ли **преимущества** для вашего случая использования **недостатки**. 🤓 +Убедитесь, что вы оценили, компенсируют ли **выгоды** для вашего случая использования **недостатки**. 🤓 /// @@ -19,37 +19,37 @@ Вот некоторые из библиотек **GraphQL**, которые поддерживают **ASGI**. Вы можете использовать их с **FastAPI**: * Strawberry 🍓 - * С документацией по FastAPI + * С документацией для FastAPI * Ariadne - * С документацией по FastAPI + * С документацией для FastAPI * Tartiflette - * С Tartiflette ASGI для интеграции с ASGI + * С Tartiflette ASGI для обеспечения интеграции с ASGI * Graphene * С starlette-graphene3 -## GraphQL с Strawberry +## GraphQL с использованием Strawberry -Если вам нужно или вы хотите работать с **GraphQL**, **Strawberry** — это **рекомендуемая** библиотека, так как она имеет дизайн, близкий к дизайну **FastAPI**, и основана на **аннотациях типов**. +Если вам нужно или вы хотите работать с **GraphQL**, библиотека **Strawberry** является **рекомендуемой**, так как ее дизайн наиболее близок к дизайну **FastAPI**, и всё основано на **аннотациях типов**. -В зависимости от вашего случая использования, вы можете предпочесть другую библиотеку, но если спросите меня, я скорее всего предложу вам попробовать **Strawberry**. +В зависимости от вашего случая использования, вы можете предпочесть другую библиотеку, но если бы вы спросили меня, я бы, вероятно, предложил попробовать **Strawberry**. -Вот небольшой пример того, как вы можете интегрировать Strawberry с FastAPI: +Вот небольшой пример того, как можно интегрировать Strawberry с FastAPI: {* ../../docs_src/graphql/tutorial001.py hl[3,22,25] *} Вы можете узнать больше о Strawberry в документации Strawberry. -Также обратите внимание на документацию о Strawberry с FastAPI. +А также документацию о Strawberry с FastAPI. -## Более старая `GraphQLApp` из Starlette +## Устаревший `GraphQLApp` от Starlette -Предыдущие версии Starlette включали класс `GraphQLApp` для интеграции с Graphene. +В предыдущих версиях Starlette включалась класс `GraphQLApp` для интеграции с Graphene. -Он был исключен из Starlette, но если у вас есть код, который его использует, вы можете легко **мигрировать** на starlette-graphene3, которая охватывает тот же случай использования и имеет **почти идентичный интерфейс**. +Он был исключен из Starlette, но если у вас есть код, который использует его, вы можете легко **мигрировать** на starlette-graphene3, который покрывает тот же случай использования и имеет **почти идентичный интерфейс**. /// tip | Совет -Если вам нужен GraphQL, я все же рекомендую вам обратить внимание на Strawberry, так как он основан на аннотациях типов, а не на пользовательских классах и типах. +Если вам нужен GraphQL, я всё же рекомендую обратить внимание на Strawberry, так как он основан на аннотациях типов, а не на кастомных классах и типах. /// @@ -57,4 +57,4 @@ Вы можете узнать больше о **GraphQL** в официальной документации GraphQL. -Вы также можете прочитать больше о каждой из упомянутых выше библиотек по предоставленным ссылкам. +Также вы можете прочитать больше о каждой из описанных выше библиотек по предоставленным ссылкам. diff --git a/docs/ru/docs/how-to/index.md b/docs/ru/docs/how-to/index.md index d1d8fec0f..7c6db10ab 100644 --- a/docs/ru/docs/how-to/index.md +++ b/docs/ru/docs/how-to/index.md @@ -1,13 +1,13 @@ # Как сделать - Рецепты -Здесь вы найдете различные рецепты или руководства «как сделать» по **разным темам**. +Здесь вы найдете различные рецепты или руководства "как сделать" для **различных тем**. -Большинство из этих идей будут более или менее **независимыми**, и в большинстве случаев вам нужно изучать их только в случае, если они применимы непосредственно к **вашему проекту**. +Большинство этих идей будут более или менее **независимыми**, и в большинстве случаев вам следует изучать их только в том случае, если они напрямую применимы к **вашему проекту**. -Если что-то кажется интересным и полезным для вашего проекта, смело проверяйте это, но в противном случае вы, вероятно, сможете просто их пропустить. +Если что-то кажется интересным и полезным для вашего проекта, смело изучайте это, в противном случае вы можете просто пропустить их. /// tip | Совет -Если вы хотите **изучить FastAPI** структурированным образом (рекомендуется), идите и читайте [Учебник - Руководство пользователя](../tutorial/index.md){.internal-link target=_blank} глава за главой. +Если вы хотите **изучить FastAPI** структурированным образом (рекомендуется), прочитайте [Учебник - Руководство пользователя](../tutorial/index.md){.internal-link target=_blank} главу за главой. /// diff --git a/docs/ru/docs/how-to/separate-openapi-schemas.md b/docs/ru/docs/how-to/separate-openapi-schemas.md index 00b2f2da7..c970cbc03 100644 --- a/docs/ru/docs/how-to/separate-openapi-schemas.md +++ b/docs/ru/docs/how-to/separate-openapi-schemas.md @@ -1,28 +1,28 @@ -# Раздельные схемы OpenAPI для ввода и вывода или нет +# Отдельные схемы OpenAPI для ввода и вывода или нет -При использовании **Pydantic v2** созданный OpenAPI немного более точен и **правилен**, чем раньше. 😎 +При использовании **Pydantic v2** сгенерированный OpenAPI более точный и **правильный**, чем раньше. 😎 -Фактически, в некоторых случаях, для одной и той же модели Pydantic в OpenAPI даже будет **две схемы JSON** — для ввода и вывода, в зависимости от того, имеют ли они **значения по умолчанию**. +Фактически, в некоторых случаях, будет даже **две схемы JSON** в OpenAPI для одной и той же модели Pydantic: для ввода и вывода, в зависимости от наличия **значений по умолчанию**. -Посмотрим, как это работает, и как изменить это, если вам нужно это сделать. +Давайте посмотрим, как это работает и как изменить это, если необходимо. -## Pydantic модели для ввода и вывода +## Модели Pydantic для ввода и вывода -Предположим, у вас есть модель Pydantic со значениями по умолчанию, например, такая: +Предположим, у вас есть модель Pydantic со значениями по умолчанию, как эта: {* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:7] hl[7] *} ### Модель для ввода -Если вы используете эту модель в качестве входных данных, как здесь: +Если использовать эту модель для ввода, как здесь: {* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:15] hl[14] *} -...тогда поле `description` **не будет обязательным**. Потому что у него есть значение по умолчанию `None`. +...то поле `description` **не будет обязательным**. Потому что у него есть значение по умолчанию `None`. ### Модель ввода в документации -Вы можете подтвердить в документации, что поле `description` не имеет **красной звездочки**, оно не помечено как обязательное: +Вы можете убедиться в этом, посмотрев документацию: поле `description` не помечено как обязательное **красной звездочкой**:
@@ -30,34 +30,34 @@ ### Модель для вывода -Но если вы используете ту же модель для вывода, как здесь: +Но если использовать ту же модель для вывода, как здесь: {* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *} -...тогда, так как `description` имеет значение по умолчанию, если вы **ничего не возвращаете** для этого поля, оно все равно будет иметь это **значение по умолчанию**. +...тогда, поскольку `description` имеет значение по умолчанию, если вы **ничего не вернете** для этого поля, оно по-прежнему будет иметь это **значение по умолчанию**. -### Модель для данных ответа вывода +### Модель для данных ответа -Если вы взаимодействуете с документацией и проверяете ответ, даже если код ничего не добавил в одно из полей `description`, JSON ответ содержит значение по умолчанию (`null`): +Если вы взаимодействуете с документацией и проверяете ответ, даже если в коде ничего не добавлялось в одно из полей `description`, JSON-ответ содержит значение по умолчанию (`null`):
-Это означает, что у него **всегда будет значение**, просто иногда это значение может быть `None` (или `null` в терминах JSON). +Это означает, что у него **всегда будет значение**, просто иногда это значение может быть `None` (или `null` в JSON). -Это означает, что клиенты, использующие ваш API, не должны проверять, существует значение или нет, они могут **предполагать, что поле всегда будет там**, но в некоторых случаях у него будет значение по умолчанию `None`. +Это значит, что клиенты, использующие ваш API, не должны проверять, существует ли значение, они могут **предполагать, что поле всегда будет**, но в некоторых случаях оно будет иметь значение по умолчанию `None`. -Способ описания этого в OpenAPI состоит в том, чтобы пометить это поле как **обязательное**, поскольку оно всегда будет там. +Способ описать это в OpenAPI — отметить это поле как **обязательное**, потому что оно всегда будет присутствовать. -Из-за этого схема JSON для модели может отличаться в зависимости от того, используется ли она для **ввода или вывода**: +Из-за этого, схема JSON для модели может отличаться в зависимости от того, используется она для **ввода или вывода**: * для **ввода** `description` **не будет обязательным** -* для **вывода** оно будет **обязательным** (и возможно `None`, или в терминах JSON `null`) +* для **вывода** оно будет **обязательным** (и возможно `None`, или в терминах JSON, `null`) ### Модель для вывода в документации -Вы тоже можете проверить модель вывода в документации, **оба** поля `name` и `description` помечены как **обязательные** с **красной звездочкой**: +Вы также можете проверить модель вывода в документации, **оба** поля `name` и `description` отмечены как **обязательные** с **красной звездочкой**:
@@ -65,40 +65,40 @@ ### Модель для ввода и вывода в документации -И если вы проверите все доступные схемы (JSON схемы) в OpenAPI, вы увидите, что их две, одна `Item-Input` и одна `Item-Output`. +И если вы проверите все доступные схемы (JSON схемы) в OpenAPI, вы увидите, что их две: `Item-Input` и `Item-Output`. -Для `Item-Input` `description` **не является обязательным**, у него нет красной звездочки. +Для `Item-Input` `description` **не обязателен**, у него нет красной звездочки. -Но для `Item-Output` `description` является **обязательным**, у него есть красная звездочка. +Но для `Item-Output` `description` **обязателен**, у него есть красная звездочка.
-С этой функцией из **Pydantic v2** ваша документация API становится более **точной**, и если у вас есть автоматически сгенерированные клиенты и SDK, они также будут более точными, с лучшим **опытом разработчика** и согласованностью. 🎉 +С этой функцией из **Pydantic v2**, ваша документация API более **точная**, и если у вас есть автоматически сгенерированные клиенты и SDK, они будут более точными тоже, с более лучшим **опытом разработчика** и консистентностью. 🎉 -## Не разделяйте схемы +## Не разделять схемы -Теперь, в некоторых случаях вы, возможно, захотите иметь **одну и ту же схему для ввода и вывода**. +Теперь, есть случаи, когда вы можете захотеть иметь **одну и ту же схему для ввода и вывода**. -Возможно, главным случаем использования является то, что если у вас уже есть сгенерированный клиентский код/SDK, и вы не хотите обновлять весь клиентский код/SDK пока, вы, вероятно, захотите сделать это в какой-то момент, но, возможно, не сейчас. +Возможно, основным случаем использования будет, если у вас уже есть какой-то автоматически сгенерированный клиентский код/SDK, и вы не хотите обновлять весь автоматически сгенерированный клиентский код/SDK еще. Вы, вероятно, захотите сделать это в какой-то момент, но, возможно, не прямо сейчас. В этом случае вы можете отключить эту функцию в **FastAPI** с параметром `separate_input_output_schemas=False`. /// info | Информация -Поддержка `separate_input_output_schemas` была добавлена ​​в FastAPI `0.102.0`. 🤓 +Поддержка `separate_input_output_schemas` была добавлена в FastAPI в версии `0.102.0`. 🤓 /// {* ../../docs_src/separate_openapi_schemas/tutorial002_py310.py hl[10] *} -### Одна и та же схема для моделей ввода и вывода в документации +### Одинаковая схема для вводных и выводных моделей в документации -И теперь будет одна единая схема для ввода и вывода для модели, только `Item`, и в ней `description` будет **необязательным**: +И теперь будет одна единственная схема для ввода и вывода для модели, только `Item`, и `description` будет **необязательным**:
-Это то же самое поведение, что и в Pydantic v1. 🤓 +Это такое же поведение, как в Pydantic v1. 🤓 diff --git a/docs/ru/docs/how-to/testing-database.md b/docs/ru/docs/how-to/testing-database.md index 3c6af7878..1c674af88 100644 --- a/docs/ru/docs/how-to/testing-database.md +++ b/docs/ru/docs/how-to/testing-database.md @@ -2,6 +2,6 @@ Вы можете изучить базы данных, SQL и SQLModel в документации SQLModel. 🤓 -Есть мини-руководство по использованию SQLModel с FastAPI. ✨ +Есть мини учебное пособие по использованию SQLModel с FastAPI. ✨ -Это руководство включает раздел о тестировании SQL баз данных. 😎 +Этот учебник включает в себя раздел о тестировании SQL баз данных. 😎 diff --git a/docs/ru/docs/resources/index.md b/docs/ru/docs/resources/index.md index 208379e46..a04a36e3d 100644 --- a/docs/ru/docs/resources/index.md +++ b/docs/ru/docs/resources/index.md @@ -1,3 +1,3 @@ # Ресурсы -Дополнительные ресурсы, внешние ссылки, статьи и многое другое. ✈️ +Дополнительные ресурсы, внешние ссылки, статьи и другое. ✈️