diff --git a/docs/ru/docs/advanced/additional-responses.md b/docs/ru/docs/advanced/additional-responses.md index fca4f072d..ca36ba20e 100644 --- a/docs/ru/docs/advanced/additional-responses.md +++ b/docs/ru/docs/advanced/additional-responses.md @@ -26,7 +26,7 @@ Например, чтобы объявить ещё один ответ со статус-кодом `404` и Pydantic-моделью `Message`, можно написать: -{* ../../docs_src/additional_responses/tutorial001_py39.py hl[18,22] *} +{* ../../docs_src/additional_responses/tutorial001_py310.py hl[18,22] *} /// note | Примечание @@ -203,7 +203,7 @@ А также ответ со статус-кодом `200`, который использует ваш `response_model`, но включает пользовательский `example`: -{* ../../docs_src/additional_responses/tutorial003_py39.py hl[20:31] *} +{* ../../docs_src/additional_responses/tutorial003_py310.py hl[20:31] *} Всё это будет объединено и включено в ваш OpenAPI и отображено в документации API: diff --git a/docs/ru/docs/advanced/advanced-dependencies.md b/docs/ru/docs/advanced/advanced-dependencies.md index fb2643cd5..686a0cf91 100644 --- a/docs/ru/docs/advanced/advanced-dependencies.md +++ b/docs/ru/docs/advanced/advanced-dependencies.md @@ -18,7 +18,7 @@ Для этого объявляем метод `__call__`: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[12] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[12] *} В этом случае именно `__call__` **FastAPI** использует для проверки дополнительных параметров и подзависимостей, и именно он будет вызван, чтобы позже передать значение параметру в вашей *функции-обработчике пути*. @@ -26,7 +26,7 @@ Теперь мы можем использовать `__init__`, чтобы объявить параметры экземпляра, с помощью которых будем «параметризовать» зависимость: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[9] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[9] *} В этом случае **FastAPI** вовсе не трогает `__init__` и не зависит от него — мы используем его напрямую в нашем коде. @@ -34,7 +34,7 @@ Мы можем создать экземпляр этого класса так: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[18] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *} Так мы «параметризуем» нашу зависимость: теперь внутри неё хранится "bar" в атрибуте `checker.fixed_content`. @@ -50,7 +50,7 @@ checker(q="somequery") …и передаст возвращённое значение как значение зависимости в параметр `fixed_content_included` нашей *функции-обработчика пути*: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[22] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *} /// tip | Совет diff --git a/docs/ru/docs/advanced/advanced-python-types.md b/docs/ru/docs/advanced/advanced-python-types.md new file mode 100644 index 000000000..62dcf8c4f --- /dev/null +++ b/docs/ru/docs/advanced/advanced-python-types.md @@ -0,0 +1,61 @@ +# Продвинутые типы Python { #advanced-python-types } + +Ниже несколько дополнительных идей, которые могут быть полезны при работе с типами Python. + +## Использование `Union` или `Optional` { #using-union-or-optional } + +Если по какой-то причине ваш код не может использовать `|`, например, если это не аннотация типов, а что-то вроде `response_model=`, вместо вертикальной черты (`|`) можно использовать `Union` из `typing`. + +Например, вы можете объявить, что значение может быть `str` или `None`: + +```python +from typing import Union + + +def say_hi(name: Union[str, None]): + print(f"Hi {name}!") +``` + +В `typing` также есть сокращение, чтобы объявить, что значение может быть `None`, — `Optional`. + +Вот совет с моей очень субъективной точки зрения: + +- 🚨 Избегайте использования `Optional[SomeType]` +- Вместо этого ✨ используйте **`Union[SomeType, None]`** ✨. + +Оба варианта эквивалентны и под капотом это одно и то же, но я бы рекомендовал `Union` вместо `Optional`, потому что слово «optional» может наводить на мысль, что значение необязательное, тогда как на самом деле это означает «значение может быть `None`», даже если оно не является необязательным и по-прежнему требуется. + +По-моему, `Union[SomeType, None]` более явно передаёт смысл. + +Речь только о словах и названиях. Но эти слова могут влиять на то, как вы и ваша команда думаете о коде. + +В качестве примера возьмём такую функцию: + +```python +from typing import Optional + + +def say_hi(name: Optional[str]): + print(f"Hey {name}!") +``` + +Параметр `name` объявлен как `Optional[str]`, но он не является необязательным: вы не можете вызвать функцию без этого параметра: + +```Python +say_hi() # О нет, это вызывает ошибку! 😱 +``` + +Параметр `name` по-прежнему обязателен (не «optional»), так как у него нет значения по умолчанию. При этом `name` принимает `None` в качестве значения: + +```Python +say_hi(name=None) # Это работает, None допустим 🎉 +``` + +Хорошая новость: в большинстве случаев вы сможете просто использовать `|` для объявления объединений типов: + +```python +def say_hi(name: str | None): + print(f"Hey {name}!") +``` + +Так что обычно вам не о чем переживать из‑за названий вроде `Optional` и `Union`. 😎 diff --git a/docs/ru/docs/advanced/async-tests.md b/docs/ru/docs/advanced/async-tests.md index e68970406..52939c255 100644 --- a/docs/ru/docs/advanced/async-tests.md +++ b/docs/ru/docs/advanced/async-tests.md @@ -32,11 +32,11 @@ Файл `main.py`: -{* ../../docs_src/async_tests/app_a_py39/main.py *} +{* ../../docs_src/async_tests/app_a_py310/main.py *} Файл `test_main.py` содержит тесты для `main.py`, теперь он может выглядеть так: -{* ../../docs_src/async_tests/app_a_py39/test_main.py *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py *} ## Запуск тестов { #run-it } @@ -56,7 +56,7 @@ $ pytest Маркер `@pytest.mark.anyio` говорит pytest, что тестовая функция должна быть вызвана асинхронно: -{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[7] *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[7] *} /// tip | Подсказка @@ -66,7 +66,7 @@ $ pytest Затем мы можем создать `AsyncClient` со ссылкой на приложение и посылать асинхронные запросы, используя `await`. -{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[9:12] *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[9:12] *} Это эквивалентно следующему: @@ -94,6 +94,6 @@ response = client.get('/') /// tip | Подсказка -Если вы столкнулись с `RuntimeError: Task attached to a different loop` при вызове асинхронных функций в ваших тестах (например, при использовании MongoDB's MotorClient), то не забывайте инициализировать объекты, которым нужен цикл событий (event loop), только внутри асинхронных функций, например, в `'@app.on_event("startup")` callback. +Если вы столкнулись с `RuntimeError: Task attached to a different loop` при вызове асинхронных функций в ваших тестах (например, при использовании MongoDB's MotorClient), то не забывайте инициализировать объекты, которым нужен цикл событий (event loop), только внутри асинхронных функций, например, в `@app.on_event("startup")` callback. /// diff --git a/docs/ru/docs/advanced/behind-a-proxy.md b/docs/ru/docs/advanced/behind-a-proxy.md index f78da01a0..ec75ed369 100644 --- a/docs/ru/docs/advanced/behind-a-proxy.md +++ b/docs/ru/docs/advanced/behind-a-proxy.md @@ -44,7 +44,7 @@ $ fastapi run --forwarded-allow-ips="*" Например, вы объявили операцию пути `/items/`: -{* ../../docs_src/behind_a_proxy/tutorial001_01_py39.py hl[6] *} +{* ../../docs_src/behind_a_proxy/tutorial001_01_py310.py hl[6] *} Если клиент обратится к `/items`, по умолчанию произойдёт редирект на `/items/`. @@ -115,7 +115,7 @@ sequenceDiagram Хотя весь ваш код написан с расчётом, что путь один — `/app`. -{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[6] *} +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *} Прокси будет «обрезать» префикс пути на лету перед передачей запроса на сервер приложения (скорее всего Uvicorn, запущенный через FastAPI CLI), поддерживая у вашего приложения иллюзию, что его обслуживают по `/app`, чтобы вам не пришлось менять весь код и добавлять префикс `/api/v1`. @@ -193,7 +193,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 Здесь мы добавляем его в сообщение лишь для демонстрации. -{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[8] *} +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *} Затем, если вы запустите Uvicorn так: @@ -220,7 +220,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 Если нет возможности передать опцию командной строки `--root-path` (или аналог), вы можете указать параметр `root_path` при создании приложения FastAPI: -{* ../../docs_src/behind_a_proxy/tutorial002_py39.py hl[3] *} +{* ../../docs_src/behind_a_proxy/tutorial002_py310.py hl[3] *} Передача `root_path` в `FastAPI` эквивалентна опции командной строки `--root-path` для Uvicorn или Hypercorn. @@ -241,17 +241,17 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 Uvicorn ожидает, что прокси обратится к нему по `http://127.0.0.1:8000/app`, а уже задача прокси — добавить сверху префикс `/api/v1`. -## О прокси с урезанным префиксом пути { #about-proxies-with-a-stripped-path-prefix } +## О прокси с функцией удаления префикса пути { #about-proxies-with-a-stripped-path-prefix } -Помните, что прокси с урезанным префиксом пути — лишь один из вариантов настройки. +Помните, что прокси с функцией удаления префикса пути — лишь один из вариантов настройки. -Во многих случаях по умолчанию прокси будет без урезанного префикса пути. +Во многих случаях по умолчанию прокси будет без функции удаления префикса пути. -В таком случае (без урезанного префикса) прокси слушает, например, по адресу `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`. +В таком случае (без функции удаления префикса пути) прокси слушает, например, по адресу `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`. ## Локальное тестирование с Traefik { #testing-locally-with-traefik } -Вы можете легко поэкспериментировать локально с урезанным префиксом пути, используя Traefik. +Вы можете легко поэкспериментировать локально с функцией удаления префикса пути, используя Traefik. Скачайте Traefik — это один бинарный файл; распакуйте архив и запустите его прямо из терминала. @@ -400,7 +400,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 Например: -{* ../../docs_src/behind_a_proxy/tutorial003_py39.py hl[4:7] *} +{* ../../docs_src/behind_a_proxy/tutorial003_py310.py hl[4:7] *} Будет сгенерирована схема OpenAPI примерно такая: @@ -455,7 +455,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 Если вы не хотите, чтобы FastAPI добавлял автоматический сервер, используя `root_path`, укажите параметр `root_path_in_servers=False`: -{* ../../docs_src/behind_a_proxy/tutorial004_py39.py hl[9] *} +{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[9] *} и тогда этот сервер не будет добавлен в схему OpenAPI. diff --git a/docs/ru/docs/advanced/custom-response.md b/docs/ru/docs/advanced/custom-response.md index 49550b49f..b9f91373d 100644 --- a/docs/ru/docs/advanced/custom-response.md +++ b/docs/ru/docs/advanced/custom-response.md @@ -30,7 +30,7 @@ Но если вы уверены, что содержимое, которое вы возвращаете, **сериализуемо в JSON**, вы можете передать его напрямую в класс ответа и избежать дополнительных накладных расходов, которые FastAPI понёс бы, пропуская возвращаемое содержимое через `jsonable_encoder` перед передачей в класс ответа. -{* ../../docs_src/custom_response/tutorial001b_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *} /// info | Информация @@ -55,7 +55,7 @@ - Импортируйте `HTMLResponse`. - Передайте `HTMLResponse` в параметр `response_class` вашего декоратора операции пути. -{* ../../docs_src/custom_response/tutorial002_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} /// info | Информация @@ -73,17 +73,17 @@ Тот же пример сверху, возвращающий `HTMLResponse`, может выглядеть так: -{* ../../docs_src/custom_response/tutorial003_py39.py hl[2,7,19] *} +{* ../../docs_src/custom_response/tutorial003_py310.py hl[2,7,19] *} /// warning | Предупреждение -`Response`, возвращённый напрямую вашей функцией-обработчиком пути, не будет задокументирован в OpenAPI (например, `Content-Type` нне будет задокументирова) и не будет виден в автоматически сгенерированной интерактивной документации. +`Response`, возвращённый напрямую вашей функцией-обработчиком пути, не будет задокументирован в OpenAPI (например, `Content-Type` не будет задокументирован) и не будет виден в автоматически сгенерированной интерактивной документации. /// /// info | Информация -Разумеется, фактические заголовок `Content-Type`, статус-код и т.д. возьмутся из объекта `Response`, который вы вернули. +Разумеется, фактический заголовок `Content-Type`, статус-код и т.д. возьмутся из объекта `Response`, который вы вернули. /// @@ -97,7 +97,7 @@ Например, это может быть что-то вроде: -{* ../../docs_src/custom_response/tutorial004_py39.py hl[7,21,23] *} +{* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *} В этом примере функция `generate_html_response()` уже генерирует и возвращает `Response` вместо возврата HTML в `str`. @@ -136,7 +136,7 @@ FastAPI (фактически Starlette) автоматически добавит заголовок Content-Length. Также будет добавлен заголовок Content-Type, основанный на `media_type` и с добавлением charset для текстовых типов. -{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *} +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} ### `HTMLResponse` { #htmlresponse } @@ -146,7 +146,7 @@ FastAPI (фактически Starlette) автоматически добави Принимает текст или байты и возвращает ответ в виде простого текста. -{* ../../docs_src/custom_response/tutorial005_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial005_py310.py hl[2,7,9] *} ### `JSONResponse` { #jsonresponse } @@ -180,7 +180,7 @@ FastAPI (фактически Starlette) автоматически добави /// -{* ../../docs_src/custom_response/tutorial001_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *} /// tip | Совет @@ -194,13 +194,13 @@ FastAPI (фактически Starlette) автоматически добави Вы можете вернуть `RedirectResponse` напрямую: -{* ../../docs_src/custom_response/tutorial006_py39.py hl[2,9] *} +{* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *} --- Или можно использовать его в параметре `response_class`: -{* ../../docs_src/custom_response/tutorial006b_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *} Если вы сделаете так, то сможете возвращать URL напрямую из своей функции-обработчика пути. @@ -210,13 +210,13 @@ FastAPI (фактически Starlette) автоматически добави Также вы можете использовать параметр `status_code` в сочетании с параметром `response_class`: -{* ../../docs_src/custom_response/tutorial006c_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial006c_py310.py hl[2,7,9] *} ### `StreamingResponse` { #streamingresponse } Принимает асинхронный генератор или обычный генератор/итератор и отправляет тело ответа потоково. -{* ../../docs_src/custom_response/tutorial007_py39.py hl[2,14] *} +{* ../../docs_src/custom_response/tutorial007_py310.py hl[2,14] *} #### Использование `StreamingResponse` с файлоподобными объектами { #using-streamingresponse-with-file-like-objects } @@ -226,7 +226,7 @@ FastAPI (фактически Starlette) автоматически добави Это включает многие библиотеки для работы с облачным хранилищем, обработки видео и т.д. -{* ../../docs_src/custom_response/tutorial008_py39.py hl[2,10:12,14] *} +{* ../../docs_src/custom_response/tutorial008_py310.py hl[2,10:12,14] *} 1. Это функция-генератор. Она является «функцией-генератором», потому что содержит оператор(ы) `yield` внутри. 2. Используя блок `with`, мы гарантируем, что файлоподобный объект будет закрыт после завершения работы функции-генератора. То есть после того, как она закончит отправку ответа. @@ -255,11 +255,11 @@ FastAPI (фактически Starlette) автоматически добави Файловые ответы будут содержать соответствующие заголовки `Content-Length`, `Last-Modified` и `ETag`. -{* ../../docs_src/custom_response/tutorial009_py39.py hl[2,10] *} +{* ../../docs_src/custom_response/tutorial009_py310.py hl[2,10] *} Вы также можете использовать параметр `response_class`: -{* ../../docs_src/custom_response/tutorial009b_py39.py hl[2,8,10] *} +{* ../../docs_src/custom_response/tutorial009b_py310.py hl[2,8,10] *} В этом случае вы можете возвращать путь к файлу напрямую из своей функции-обработчика пути. @@ -273,7 +273,7 @@ FastAPI (фактически Starlette) автоматически добави Вы могли бы создать `CustomORJSONResponse`. Главное, что вам нужно сделать — реализовать метод `Response.render(content)`, который возвращает содержимое как `bytes`: -{* ../../docs_src/custom_response/tutorial009c_py39.py hl[9:14,17] *} +{* ../../docs_src/custom_response/tutorial009c_py310.py hl[9:14,17] *} Теперь вместо того, чтобы возвращать: @@ -299,7 +299,7 @@ FastAPI (фактически Starlette) автоматически добави В примере ниже **FastAPI** будет использовать `ORJSONResponse` по умолчанию во всех операциях пути вместо `JSONResponse`. -{* ../../docs_src/custom_response/tutorial010_py39.py hl[2,4] *} +{* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *} /// tip | Совет diff --git a/docs/ru/docs/advanced/dataclasses.md b/docs/ru/docs/advanced/dataclasses.md index b3ced37c1..87a5763c1 100644 --- a/docs/ru/docs/advanced/dataclasses.md +++ b/docs/ru/docs/advanced/dataclasses.md @@ -64,7 +64,7 @@ FastAPI построен поверх **Pydantic**, и я показывал в 6. Здесь мы возвращаем словарь, содержащий `items`, который является списком dataclass. - FastAPI по-прежнему способен сериализовать данные в JSON. + FastAPI по-прежнему способен сериализовать данные в JSON. 7. Здесь `response_model` использует аннотацию типа — список dataclass `Author`. diff --git a/docs/ru/docs/advanced/events.md b/docs/ru/docs/advanced/events.md index db73d9094..bcb5b000a 100644 --- a/docs/ru/docs/advanced/events.md +++ b/docs/ru/docs/advanced/events.md @@ -30,7 +30,7 @@ Мы создаём асинхронную функцию `lifespan()` с `yield` примерно так: -{* ../../docs_src/events/tutorial003_py39.py hl[16,19] *} +{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} Здесь мы симулируем дорогую операцию startup по загрузке модели, помещая (фиктивную) функцию модели в словарь с моделями Машинного обучения до `yield`. Этот код будет выполнен до того, как приложение начнет принимать запросы, во время startup. @@ -48,7 +48,7 @@ Первое, на что стоит обратить внимание, — мы определяем асинхронную функцию с `yield`. Это очень похоже на Зависимости с `yield`. -{* ../../docs_src/events/tutorial003_py39.py hl[14:19] *} +{* ../../docs_src/events/tutorial003_py310.py hl[14:19] *} Первая часть функции, до `yield`, будет выполнена до запуска приложения. @@ -60,7 +60,7 @@ Это превращает функцию в «асинхронный менеджер контекста». -{* ../../docs_src/events/tutorial003_py39.py hl[1,13] *} +{* ../../docs_src/events/tutorial003_py310.py hl[1,13] *} Менеджер контекста в Python — это то, что можно использовать в операторе `with`. Например, `open()` можно использовать как менеджер контекста: @@ -82,7 +82,7 @@ async with lifespan(app): Параметр `lifespan` приложения `FastAPI` принимает асинхронный менеджер контекста, поэтому мы можем передать ему наш новый асинхронный менеджер контекста `lifespan`. -{* ../../docs_src/events/tutorial003_py39.py hl[22] *} +{* ../../docs_src/events/tutorial003_py310.py hl[22] *} ## Альтернативные события (устаревшие) { #alternative-events-deprecated } @@ -104,7 +104,7 @@ async with lifespan(app): Чтобы добавить функцию, которую нужно запустить до старта приложения, объявите её как обработчик события `"startup"`: -{* ../../docs_src/events/tutorial001_py39.py hl[8] *} +{* ../../docs_src/events/tutorial001_py310.py hl[8] *} В этом случае функция-обработчик события `startup` инициализирует «базу данных» items (это просто `dict`) некоторыми значениями. @@ -116,7 +116,7 @@ async with lifespan(app): Чтобы добавить функцию, которую нужно запустить при завершении работы приложения, объявите её как обработчик события `"shutdown"`: -{* ../../docs_src/events/tutorial002_py39.py hl[6] *} +{* ../../docs_src/events/tutorial002_py310.py hl[6] *} Здесь функция-обработчик события `shutdown` запишет строку текста `"Application shutdown"` в файл `log.txt`. diff --git a/docs/ru/docs/advanced/generate-clients.md b/docs/ru/docs/advanced/generate-clients.md index 00bdd31fe..4eb098a88 100644 --- a/docs/ru/docs/advanced/generate-clients.md +++ b/docs/ru/docs/advanced/generate-clients.md @@ -2,7 +2,7 @@ Поскольку **FastAPI** основан на спецификации **OpenAPI**, его API можно описать в стандартном формате, понятном множеству инструментов. -Это упрощает генерацию актуальной **документации**, клиентских библиотек (**SDKs**) на разных языках, а также **тестирования** или **воркфлоу автоматизации**, которые остаются синхронизированными с вашим кодом. +Это упрощает генерацию актуальной **документации**, клиентских библиотек (**SDKs**) на разных языках, а также **тестирования** или **воркфлоу автоматизации**, которые остаются синхронизированными с вашим кодом. В этом руководстве вы узнаете, как сгенерировать **TypeScript SDK** для вашего бэкенда на FastAPI. @@ -40,7 +40,7 @@ FastAPI автоматически генерирует спецификации Начнём с простого приложения FastAPI: -{* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *} +{* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *} Обратите внимание, что *операции пути (обработчики пути)* определяют модели, которые они используют для полезной нагрузки запроса и полезной нагрузки ответа, с помощью моделей `Item` и `ResponseMessage`. @@ -98,7 +98,7 @@ npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client Например, у вас может быть раздел для **items** и другой раздел для **users**, и они могут быть разделены тегами: -{* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *} +{* ../../docs_src/generate_clients/tutorial002_py310.py hl[21,26,34] *} ### Генерация TypeScript‑клиента с тегами { #generate-a-typescript-client-with-tags } @@ -145,7 +145,7 @@ FastAPI использует **уникальный ID** для каждой *о Затем вы можете передать эту пользовательскую функцию в **FastAPI** через параметр `generate_unique_id_function`: -{* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *} +{* ../../docs_src/generate_clients/tutorial003_py310.py hl[6:7,10] *} ### Генерация TypeScript‑клиента с пользовательскими ID операций { #generate-a-typescript-client-with-custom-operation-ids } @@ -157,7 +157,7 @@ FastAPI использует **уникальный ID** для каждой *о ### Предобработка спецификации OpenAPI для генератора клиента { #preprocess-the-openapi-specification-for-the-client-generator } -Сгенерированном коде всё ещё есть **дублирующаяся информация**. +В сгенерированном коде всё ещё есть **дублирующаяся информация**. Мы уже знаем, что этот метод относится к **items**, потому что это слово есть в `ItemsService` (взято из тега), но при этом имя тега всё ещё добавлено префиксом к имени метода. 😕 @@ -167,7 +167,7 @@ FastAPI использует **уникальный ID** для каждой *о Мы можем скачать OpenAPI JSON в файл `openapi.json`, а затем **убрать этот префикс‑тег** таким скриптом: -{* ../../docs_src/generate_clients/tutorial004_py39.py *} +{* ../../docs_src/generate_clients/tutorial004_py310.py *} //// tab | Node.js diff --git a/docs/ru/docs/advanced/middleware.md b/docs/ru/docs/advanced/middleware.md index 5ebe01078..034feae7e 100644 --- a/docs/ru/docs/advanced/middleware.md +++ b/docs/ru/docs/advanced/middleware.md @@ -57,13 +57,13 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow") Любой входящий запрос по `http` или `ws` будет перенаправлен на безопасную схему. -{* ../../docs_src/advanced_middleware/tutorial001_py39.py hl[2,6] *} +{* ../../docs_src/advanced_middleware/tutorial001_py310.py hl[2,6] *} ## `TrustedHostMiddleware` { #trustedhostmiddleware } Гарантирует, что во всех входящих запросах корректно установлен `Host`‑заголовок, чтобы защититься от атак на HTTP‑заголовок Host. -{* ../../docs_src/advanced_middleware/tutorial002_py39.py hl[2,6:8] *} +{* ../../docs_src/advanced_middleware/tutorial002_py310.py hl[2,6:8] *} Поддерживаются следующие аргументы: @@ -78,7 +78,7 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow") Это middleware обрабатывает как обычные, так и потоковые ответы. -{* ../../docs_src/advanced_middleware/tutorial003_py39.py hl[2,6] *} +{* ../../docs_src/advanced_middleware/tutorial003_py310.py hl[2,6] *} Поддерживаются следующие аргументы: diff --git a/docs/ru/docs/advanced/openapi-webhooks.md b/docs/ru/docs/advanced/openapi-webhooks.md index 3a2b9fff7..b477075c1 100644 --- a/docs/ru/docs/advanced/openapi-webhooks.md +++ b/docs/ru/docs/advanced/openapi-webhooks.md @@ -16,9 +16,9 @@ Вся логика регистрации URL-адресов для вебхуков и код, который реально отправляет эти запросы, целиком на вашей стороне. Вы пишете это так, как вам нужно, в своем собственном коде. -## Документирование вебхуков с помощью FastAPI и OpenAPI { #documenting-webhooks-with-fastapi-and-openapi } +## Документирование вебхуков с помощью **FastAPI** и OpenAPI { #documenting-webhooks-with-fastapi-and-openapi } -С FastAPI, используя OpenAPI, вы можете определить имена этих вебхуков, типы HTTP-операций, которые ваше приложение может отправлять (например, `POST`, `PUT` и т.д.), а также тела запросов, которые ваше приложение будет отправлять. +С **FastAPI**, используя OpenAPI, вы можете определить имена этих вебхуков, типы HTTP-операций, которые ваше приложение может отправлять (например, `POST`, `PUT` и т.д.), а также тела запросов, которые ваше приложение будет отправлять. Это значительно упростит вашим пользователям реализацию их API для приема ваших вебхук-запросов; возможно, они даже смогут автоматически сгенерировать часть кода своего API. @@ -32,7 +32,7 @@ При создании приложения на **FastAPI** есть атрибут `webhooks`, с помощью которого можно объявлять вебхуки так же, как вы объявляете операции пути (обработчики пути), например с `@app.webhooks.post()`. -{* ../../docs_src/openapi_webhooks/tutorial001_py39.py hl[9:13,36:53] *} +{* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:12,15:20] *} Определенные вами вебхуки попадут в схему **OpenAPI** и в автоматический **интерфейс документации**. diff --git a/docs/ru/docs/advanced/path-operation-advanced-configuration.md b/docs/ru/docs/advanced/path-operation-advanced-configuration.md index 86d3a5b63..b8c879bf6 100644 --- a/docs/ru/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/ru/docs/advanced/path-operation-advanced-configuration.md @@ -12,7 +12,7 @@ Нужно убедиться, что он уникален для каждой операции. -{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py310.py hl[6] *} ### Использование имени *функции-обработчика пути* как operationId { #using-the-path-operation-function-name-as-the-operationid } @@ -20,7 +20,7 @@ Делать это следует после добавления всех *операций пути*. -{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} /// tip | Совет @@ -40,7 +40,7 @@ Чтобы исключить *операцию пути* из генерируемой схемы OpenAPI (а значит, и из автоматических систем документации), используйте параметр `include_in_schema` и установите его в `False`: -{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py310.py hl[6] *} ## Расширенное описание из docstring { #advanced-description-from-docstring } @@ -92,7 +92,7 @@ `openapi_extra` может пригодиться, например, чтобы объявить [Расширения OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions): -{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py310.py hl[6] *} Если вы откроете автоматическую документацию API, ваше расширение появится внизу страницы конкретной *операции пути*. @@ -139,9 +139,9 @@ Это можно сделать с помощью `openapi_extra`: -{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py310.py hl[19:36, 39:40] *} -В этом примере мы не объявляли никакую Pydantic-модель. Фактически тело запроса даже не распарсено как JSON, оно читается напрямую как `bytes`, а функция `magic_data_reader()` будет отвечать за его парсинг каким-то способом. +В этом примере мы не объявляли никакую Pydantic-модель. Фактически тело запроса даже не распарсено как JSON, оно читается напрямую как `bytes`, а функция `magic_data_reader()` будет отвечать за его парсинг каким-то способом. Тем не менее, мы можем объявить ожидаемую схему для тела запроса. @@ -153,7 +153,7 @@ Например, в этом приложении мы не используем встроенную функциональность FastAPI для извлечения JSON Schema из моделей Pydantic, равно как и автоматическую валидацию JSON. Мы объявляем тип содержимого HTTP-запроса как YAML, а не JSON: -{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[15:20, 22] *} Тем не менее, хотя мы не используем встроенную функциональность по умолчанию, мы всё равно используем Pydantic-модель, чтобы вручную сгенерировать JSON Schema для данных, которые мы хотим получить в YAML. @@ -161,7 +161,7 @@ А затем в нашем коде мы напрямую парсим это содержимое YAML и снова используем ту же Pydantic-модель, чтобы валидировать YAML-содержимое: -{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[24:31] *} /// tip | Совет diff --git a/docs/ru/docs/advanced/response-change-status-code.md b/docs/ru/docs/advanced/response-change-status-code.md index 85d9050ff..273862bae 100644 --- a/docs/ru/docs/advanced/response-change-status-code.md +++ b/docs/ru/docs/advanced/response-change-status-code.md @@ -20,7 +20,7 @@ И затем вы можете установить `status_code` в этом *временном* объекте ответа. -{* ../../docs_src/response_change_status_code/tutorial001_py39.py hl[1,9,12] *} +{* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *} После этого вы можете вернуть любой объект, который вам нужен, как обычно (`dict`, модель базы данных и т.д.). diff --git a/docs/ru/docs/advanced/response-cookies.md b/docs/ru/docs/advanced/response-cookies.md index 2872d6c0a..d3662ef8e 100644 --- a/docs/ru/docs/advanced/response-cookies.md +++ b/docs/ru/docs/advanced/response-cookies.md @@ -6,7 +6,7 @@ Затем установить cookies в этом временном объекте ответа. -{* ../../docs_src/response_cookies/tutorial002_py39.py hl[1, 8:9] *} +{* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *} После этого можно вернуть любой объект, как и раньше (например, `dict`, объект модели базы данных и так далее). @@ -24,7 +24,7 @@ Затем установите cookies и верните этот объект: -{* ../../docs_src/response_cookies/tutorial001_py39.py hl[10:12] *} +{* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *} /// tip | Совет diff --git a/docs/ru/docs/advanced/response-directly.md b/docs/ru/docs/advanced/response-directly.md index b45281071..60facdd85 100644 --- a/docs/ru/docs/advanced/response-directly.md +++ b/docs/ru/docs/advanced/response-directly.md @@ -54,7 +54,7 @@ Вы можете поместить ваш XML-контент в строку, поместить её в `Response` и вернуть: -{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *} +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} ## Примечания { #notes } diff --git a/docs/ru/docs/advanced/response-headers.md b/docs/ru/docs/advanced/response-headers.md index 8f24f05b0..dc821983b 100644 --- a/docs/ru/docs/advanced/response-headers.md +++ b/docs/ru/docs/advanced/response-headers.md @@ -6,7 +6,7 @@ А затем вы можете устанавливать HTTP-заголовки в этом *временном* объекте ответа. -{* ../../docs_src/response_headers/tutorial002_py39.py hl[1, 7:8] *} +{* ../../docs_src/response_headers/tutorial002_py310.py hl[1, 7:8] *} После этого вы можете вернуть любой нужный объект, как обычно (например, `dict`, модель из базы данных и т.д.). @@ -22,7 +22,7 @@ Создайте ответ, как описано в [Вернуть Response напрямую](response-directly.md){.internal-link target=_blank}, и передайте заголовки как дополнительный параметр: -{* ../../docs_src/response_headers/tutorial001_py39.py hl[10:12] *} +{* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *} /// note | Технические детали diff --git a/docs/ru/docs/advanced/security/http-basic-auth.md b/docs/ru/docs/advanced/security/http-basic-auth.md index 41e62d4bf..a6bfb7c54 100644 --- a/docs/ru/docs/advanced/security/http-basic-auth.md +++ b/docs/ru/docs/advanced/security/http-basic-auth.md @@ -20,7 +20,7 @@ * Она возвращает объект типа `HTTPBasicCredentials`: * Он содержит отправленные `username` и `password`. -{* ../../docs_src/security/tutorial006_an_py39.py hl[4,8,12] *} +{* ../../docs_src/security/tutorial006_an_py310.py hl[4,8,12] *} Когда вы впервые откроете URL (или нажмёте кнопку «Execute» в документации), браузер попросит ввести имя пользователя и пароль: @@ -40,7 +40,7 @@ Затем можно использовать `secrets.compare_digest()`, чтобы убедиться, что `credentials.username` равен `"stanleyjobson"`, а `credentials.password` — `"swordfish"`. -{* ../../docs_src/security/tutorial007_an_py39.py hl[1,12:24] *} +{* ../../docs_src/security/tutorial007_an_py310.py hl[1,12:24] *} Это было бы похоже на: @@ -104,4 +104,4 @@ Pythonу придётся сравнить весь общий префикс `s После того как обнаружено, что учётные данные некорректны, верните `HTTPException` со статус-кодом ответа 401 (тем же, что и при отсутствии учётных данных) и добавьте HTTP-заголовок `WWW-Authenticate`, чтобы браузер снова показал окно входа: -{* ../../docs_src/security/tutorial007_an_py39.py hl[26:30] *} +{* ../../docs_src/security/tutorial007_an_py310.py hl[26:30] *} diff --git a/docs/ru/docs/advanced/settings.md b/docs/ru/docs/advanced/settings.md index 8408faebf..15537e2b4 100644 --- a/docs/ru/docs/advanced/settings.md +++ b/docs/ru/docs/advanced/settings.md @@ -54,7 +54,7 @@ $ pip install "fastapi[all]" Вы можете использовать все те же возможности валидации и инструменты, что и для Pydantic‑моделей, например разные типы данных и дополнительную валидацию через `Field()`. -{* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *} +{* ../../docs_src/settings/tutorial001_py310.py hl[2,5:8,11] *} /// tip | Совет @@ -70,7 +70,7 @@ $ pip install "fastapi[all]" Затем вы можете использовать новый объект `settings` в вашем приложении: -{* ../../docs_src/settings/tutorial001_py39.py hl[18:20] *} +{* ../../docs_src/settings/tutorial001_py310.py hl[18:20] *} ### Запуск сервера { #run-the-server } @@ -104,11 +104,11 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p Например, у вас может быть файл `config.py` со следующим содержимым: -{* ../../docs_src/settings/app01_py39/config.py *} +{* ../../docs_src/settings/app01_py310/config.py *} А затем использовать его в файле `main.py`: -{* ../../docs_src/settings/app01_py39/main.py hl[3,11:13] *} +{* ../../docs_src/settings/app01_py310/main.py hl[3,11:13] *} /// tip | Совет @@ -126,7 +126,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p Продолжая предыдущий пример, ваш файл `config.py` может выглядеть так: -{* ../../docs_src/settings/app02_an_py39/config.py hl[10] *} +{* ../../docs_src/settings/app02_an_py310/config.py hl[10] *} Обратите внимание, что теперь мы не создаем экземпляр по умолчанию `settings = Settings()`. @@ -134,7 +134,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p Теперь мы создаем зависимость, которая возвращает новый `config.Settings()`. -{* ../../docs_src/settings/app02_an_py39/main.py hl[6,12:13] *} +{* ../../docs_src/settings/app02_an_py310/main.py hl[6,12:13] *} /// tip | Совет @@ -146,13 +146,13 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p Затем мы можем запросить ее в *функции-обработчике пути* как зависимость и использовать там, где нужно. -{* ../../docs_src/settings/app02_an_py39/main.py hl[17,19:21] *} +{* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *} ### Настройки и тестирование { #settings-and-testing } Далее будет очень просто предоставить другой объект настроек во время тестирования, создав переопределение зависимости для `get_settings`: -{* ../../docs_src/settings/app02_an_py39/test_main.py hl[9:10,13,21] *} +{* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *} В переопределении зависимости мы задаем новое значение `admin_email` при создании нового объекта `Settings`, а затем возвращаем этот новый объект. @@ -193,7 +193,7 @@ APP_NAME="ChimichangApp" Затем обновите ваш `config.py` так: -{* ../../docs_src/settings/app03_an_py39/config.py hl[9] *} +{* ../../docs_src/settings/app03_an_py310/config.py hl[9] *} /// tip | Совет @@ -226,7 +226,7 @@ def get_settings(): Но так как мы используем декоратор `@lru_cache` сверху, объект `Settings` будет создан только один раз — при первом вызове. ✔️ -{* ../../docs_src/settings/app03_an_py39/main.py hl[1,11] *} +{* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *} Затем при любых последующих вызовах `get_settings()` в зависимостях для следующих запросов, вместо выполнения внутреннего кода `get_settings()` и создания нового объекта `Settings`, будет возвращаться тот же объект, что был возвращен при первом вызове, снова и снова. diff --git a/docs/ru/docs/advanced/sub-applications.md b/docs/ru/docs/advanced/sub-applications.md index fa5a683f4..4fd5649ce 100644 --- a/docs/ru/docs/advanced/sub-applications.md +++ b/docs/ru/docs/advanced/sub-applications.md @@ -10,7 +10,7 @@ Сначала создайте основное, верхнего уровня, приложение **FastAPI** и его *операции пути*: -{* ../../docs_src/sub_applications/tutorial001_py39.py hl[3, 6:8] *} +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[3, 6:8] *} ### Подприложение { #sub-application } @@ -18,7 +18,7 @@ Это подприложение — обычное стандартное приложение FastAPI, но именно оно будет «смонтировано»: -{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 14:16] *} +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 14:16] *} ### Смонтируйте подприложение { #mount-the-sub-application } @@ -26,7 +26,7 @@ В этом случае оно будет смонтировано по пути `/subapi`: -{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 19] *} +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 19] *} ### Проверьте автоматическую документацию API { #check-the-automatic-api-docs } diff --git a/docs/ru/docs/advanced/templates.md b/docs/ru/docs/advanced/templates.md index 460e2e466..68adcb515 100644 --- a/docs/ru/docs/advanced/templates.md +++ b/docs/ru/docs/advanced/templates.md @@ -27,7 +27,7 @@ $ pip install jinja2 - Объявите параметр `Request` в *операции пути*, которая будет возвращать шаблон. - Используйте созданный `templates`, чтобы отрендерить и вернуть `TemplateResponse`; передайте имя шаблона, объект `request` и словарь «context» с парами ключ-значение для использования внутри шаблона Jinja2. -{* ../../docs_src/templates/tutorial001_py39.py hl[4,11,15:18] *} +{* ../../docs_src/templates/tutorial001_py310.py hl[4,11,15:18] *} /// note | Примечание diff --git a/docs/ru/docs/advanced/testing-events.md b/docs/ru/docs/advanced/testing-events.md index 82caea845..452342cdd 100644 --- a/docs/ru/docs/advanced/testing-events.md +++ b/docs/ru/docs/advanced/testing-events.md @@ -2,11 +2,11 @@ Если вам нужно, чтобы `lifespan` выполнялся в ваших тестах, вы можете использовать `TestClient` вместе с оператором `with`: -{* ../../docs_src/app_testing/tutorial004_py39.py hl[9:15,18,27:28,30:32,41:43] *} +{* ../../docs_src/app_testing/tutorial004_py310.py hl[9:15,18,27:28,30:32,41:43] *} Вы можете узнать больше подробностей в статье [Запуск lifespan в тестах на официальном сайте документации Starlette.](https://www.starlette.dev/lifespan/#running-lifespan-in-tests) Для устаревших событий `startup` и `shutdown` вы можете использовать `TestClient` следующим образом: -{* ../../docs_src/app_testing/tutorial003_py39.py hl[9:12,20:24] *} +{* ../../docs_src/app_testing/tutorial003_py310.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 b6626679e..f6fa6a04b 100644 --- a/docs/ru/docs/advanced/testing-websockets.md +++ b/docs/ru/docs/advanced/testing-websockets.md @@ -4,7 +4,7 @@ Для этого используйте `TestClient` с менеджером контекста `with`, подключаясь к WebSocket: -{* ../../docs_src/app_testing/tutorial002_py39.py hl[27:31] *} +{* ../../docs_src/app_testing/tutorial002_py310.py hl[27:31] *} /// note | Примечание diff --git a/docs/ru/docs/advanced/using-request-directly.md b/docs/ru/docs/advanced/using-request-directly.md index cdf500c0e..0c091cded 100644 --- a/docs/ru/docs/advanced/using-request-directly.md +++ b/docs/ru/docs/advanced/using-request-directly.md @@ -29,7 +29,7 @@ Для этого нужно обратиться к запросу напрямую. -{* ../../docs_src/using_request_directly/tutorial001_py39.py hl[1,7:8] *} +{* ../../docs_src/using_request_directly/tutorial001_py310.py hl[1,7:8] *} Если объявить параметр *функции-обработчика пути* с типом `Request`, **FastAPI** поймёт, что нужно передать объект `Request` в этот параметр. diff --git a/docs/ru/docs/advanced/websockets.md b/docs/ru/docs/advanced/websockets.md index fa5e4738e..446cc2505 100644 --- a/docs/ru/docs/advanced/websockets.md +++ b/docs/ru/docs/advanced/websockets.md @@ -38,13 +38,13 @@ $ pip install websockets Для примера нам нужен наиболее простой способ, который позволит сосредоточиться на серверной части веб‑сокетов и получить рабочий код: -{* ../../docs_src/websockets/tutorial001_py39.py hl[2,6:38,41:43] *} +{* ../../docs_src/websockets/tutorial001_py310.py hl[2,6:38,41:43] *} ## Создание `websocket` { #create-a-websocket } Создайте `websocket` в своем **FastAPI** приложении: -{* ../../docs_src/websockets/tutorial001_py39.py hl[1,46:47] *} +{* ../../docs_src/websockets/tutorial001_py310.py hl[1,46:47] *} /// note | Технические детали @@ -58,7 +58,7 @@ $ pip install websockets Через эндпоинт веб-сокета вы можете получать и отправлять сообщения. -{* ../../docs_src/websockets/tutorial001_py39.py hl[48:52] *} +{* ../../docs_src/websockets/tutorial001_py310.py hl[48:52] *} Вы можете получать и отправлять двоичные, текстовые и JSON данные. @@ -154,7 +154,7 @@ $ fastapi dev main.py Если веб-сокет соединение закрыто, то `await websocket.receive_text()` вызовет исключение `WebSocketDisconnect`, которое можно поймать и обработать как в этом примере: -{* ../../docs_src/websockets/tutorial003_py39.py hl[79:81] *} +{* ../../docs_src/websockets/tutorial003_py310.py hl[79:81] *} Чтобы воспроизвести пример: diff --git a/docs/ru/docs/advanced/wsgi.md b/docs/ru/docs/advanced/wsgi.md index 41d3a169c..aa630c228 100644 --- a/docs/ru/docs/advanced/wsgi.md +++ b/docs/ru/docs/advanced/wsgi.md @@ -18,7 +18,7 @@ После этого смонтируйте его на путь. -{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *} +{* ../../docs_src/wsgi/tutorial001_py310.py hl[1,3,23] *} /// note | Примечание diff --git a/docs/ru/docs/alternatives.md b/docs/ru/docs/alternatives.md index 17b54aad2..1f713c3f3 100644 --- a/docs/ru/docs/alternatives.md +++ b/docs/ru/docs/alternatives.md @@ -137,7 +137,7 @@ def read_url(): ### Marshmallow { #marshmallow } -Одна из основных возможностей, нужных системам API, — «сериализация» данных, то есть преобразование данных из кода (Python) во что-то, что можно отправить по сети. Например, преобразование объекта с данными из базы в JSON-объект. Преобразование объектов `datetime` в строки и т. п. +Одна из основных возможностей, нужных системам API, — «сериализация» данных, то есть преобразование данных из кода (Python) во что-то, что можно отправить по сети. Например, преобразование объекта с данными из базы в JSON-объект. Преобразование объектов `datetime` в строки и т. п. Ещё одна важная возможность, востребованная API, — валидация данных: убеждаться, что данные валидны с учётом заданных параметров. Например, что какое-то поле — `int`, а не произвольная строка. Это особенно полезно для входящих данных. @@ -145,7 +145,7 @@ def read_url(): Именно для этих возможностей и был создан Marshmallow. Это отличная библиотека, я много ей пользовался раньше. -Но она появилась до того, как в Python появились аннотации типов. Поэтому для определения каждой схемы нужно использовать специальные утилиты и классы, предоставляемые Marshmallow. +Но она появилась до того, как в Python появились аннотации типов. Поэтому для определения каждой схемы нужно использовать специальные утилиты и классы, предоставляемые Marshmallow. /// check | Вдохновило **FastAPI** на @@ -155,7 +155,7 @@ def read_url(): ### Webargs { #webargs } -Ещё одна важная возможность для API — парсинг данных из входящих HTTP-запросов. +Ещё одна важная возможность для API — парсинг данных из входящих HTTP-запросов. Webargs — это инструмент, созданный для этого поверх нескольких фреймворков, включая Flask. @@ -245,7 +245,7 @@ Flask-apispec был создан теми же разработчиками, ч В нём встроена система внедрения зависимостей, вдохновлённая Angular 2. Требуется предварительная регистрация «инжектируемых» компонентов (как и во всех известных мне системах внедрения зависимостей), что добавляет многословности и повторяемости кода. -Поскольку параметры описываются с помощью типов TypeScript (аналог аннотаций типов в Python), поддержка редактора весьма хороша. +Поскольку параметры описываются с помощью типов TypeScript (аналог аннотаций типов в Python), поддержка редактора кода весьма хороша. Но так как данные о типах TypeScript не сохраняются после компиляции в JavaScript, он не может полагаться на типы для одновременного определения валидации, сериализации и документации. Из‑за этого и некоторых проектных решений для получения валидации, сериализации и автоматической генерации схем приходится добавлять декораторы во многих местах. В итоге это становится довольно многословным. @@ -359,7 +359,7 @@ Hug вдохновил **FastAPI** объявлять параметр `response В нём были автоматические валидация данных, сериализация данных и генерация схемы OpenAPI на основе тех же аннотаций типов в нескольких местах. -Определение схемы тела запроса не использовало те же аннотации типов Python, как в Pydantic, — это было ближе к Marshmallow, поэтому поддержка редактора была бы хуже, но всё равно APIStar оставался лучшим доступным вариантом. +Определение схемы тела запроса не использовало те же аннотации типов Python, как в Pydantic, — это было ближе к Marshmallow, поэтому поддержка редактора кода была бы хуже, но всё равно APIStar оставался лучшим доступным вариантом. На тот момент у него были лучшие показатели в бенчмарках (его превосходил только Starlette). @@ -419,7 +419,7 @@ Pydantic — это библиотека для определения вали ### Starlette { #starlette } -Starlette — это лёгкий ASGI фреймворк/набор инструментов, идеально подходящий для создания высокопроизводительных asyncio‑сервисов. +Starlette — это лёгкий ASGI фреймворк/набор инструментов, идеально подходящий для создания высокопроизводительных asyncio‑сервисов. Он очень простой и интуитивный. Спроектирован так, чтобы его было легко расширять, и чтобы компоненты были модульными. diff --git a/docs/ru/docs/async.md b/docs/ru/docs/async.md index 15d4e108a..bff32aaf4 100644 --- a/docs/ru/docs/async.md +++ b/docs/ru/docs/async.md @@ -4,7 +4,7 @@ ## Нет времени? { #in-a-hurry } -TL;DR: +TL;DR: Если вы используете сторонние библиотеки, которые нужно вызывать с `await`, например: @@ -68,13 +68,13 @@ def results(): Асинхронный код значит, что в языке 💬 есть способ сказать компьютеру/программе 🤖, что в некоторый момент кода ему 🤖 придётся подождать, пока *что-то ещё* где-то в другом месте завершится. Назовём это *что-то ещё* «медленный файл» 📝. -И пока мы ждём завершения работы с «медленныи файлом» 📝, компьютер может заняться другой работой. +И пока мы ждём завершения работы с «медленным файлом» 📝, компьютер может заняться другой работой. Затем компьютер/программа 🤖 будет возвращаться каждый раз, когда появится возможность (пока снова где-то идёт ожидание), или когда 🤖 завершит всю текущую работу. И он 🤖 проверит, не завершилась ли какая-либо из задач, которых он ждал, и сделает то, что нужно. Далее он 🤖 возьмёт первую завершившуюся задачу (скажем, наш «медленный файл» 📝) и продолжит делать с ней то, что требуется. -Это «ожидание чего-то ещё» обычно относится к операциям I/O, которые относительно «медленные» (по сравнению со скоростью процессора и оперативной памяти), например ожидание: +Это «ожидание чего-то ещё» обычно относится к операциям I/O, которые относительно «медленные» (по сравнению со скоростью процессора и оперативной памяти), например ожидание: * отправки данных клиентом по сети * получения клиентом данных, отправленных вашей программой по сети @@ -85,7 +85,7 @@ def results(): * возврата результатов запроса к базе данных * и т.д. -Поскольку основное время выполнения уходит на ожидание операций I/O, их называют операциями, «ограниченными вводом-выводом» (I/O bound). +Поскольку основное время выполнения уходит на ожидание операций I/O, их называют операциями, «ограниченными вводом-выводом» (I/O bound). Это называется «асинхронным», потому что компьютеру/программе не нужно «синхронизироваться» с медленной задачей, простаивая и выжидая точный момент её завершения, чтобы забрать результат и продолжить работу. @@ -277,7 +277,7 @@ def results(): В этом сценарии каждый уборщик (включая вас) был бы процессором, выполняющим свою часть работы. -И так как основное время выполнения уходит на реальную работу (а не ожидание), а работу в компьютере выполняет CPU, такие задачи называют «ограниченными процессором» (CPU bound). +И так как основное время выполнения уходит на реальную работу (а не ожидание), а работу в компьютере выполняет CPU, такие задачи называют «ограниченными процессором» (CPU bound). --- @@ -417,7 +417,7 @@ Starlette (и **FastAPI**) основаны на I/O. +Если вы пришли из другого async-фреймворка, который работает иначе, и привыкли объявлять тривиальные *функции-обработчики пути*, выполняющие только вычисления, через простой `def` ради крошечной выгоды в производительности (около 100 наносекунд), обратите внимание: в **FastAPI** эффект будет противоположным. В таких случаях лучше использовать `async def`, если только ваши *функции-обработчики пути* не используют код, выполняющий блокирующий I/O. Тем не менее, в обоих случаях велика вероятность, что **FastAPI** [всё равно будет быстрее](index.md#performance){.internal-link target=_blank} (или как минимум сопоставим) с вашим предыдущим фреймворком. diff --git a/docs/ru/docs/benchmarks.md b/docs/ru/docs/benchmarks.md index 612b39f70..c8cacae5f 100644 --- a/docs/ru/docs/benchmarks.md +++ b/docs/ru/docs/benchmarks.md @@ -16,19 +16,19 @@ * **Uvicorn**: ASGI-сервер * **Starlette**: (использует Uvicorn) веб-микрофреймворк - * **FastAPI**: (использует Starlette) API-микрофреймворк с рядом дополнительных возможностей для создания API, включая валидацию данных и т. п. + * **FastAPI**: (использует Starlette) API-микрофреймворк с рядом дополнительных возможностей для создания API, включая валидацию данных и т.п. * **Uvicorn**: * Будет иметь наилучшую производительность, так как помимо самого сервера у него немного дополнительного кода. * Вы не будете писать приложение непосредственно на Uvicorn. Это означало бы, что Ваш код должен включать как минимум весь код, предоставляемый Starlette (или **FastAPI**). И если Вы так сделаете, то в конечном итоге Ваше приложение будет иметь те же накладные расходы, что и при использовании фреймворка, минимизирующего код Вашего приложения и Ваши ошибки. - * Если Вы сравниваете Uvicorn, сравнивайте его с Daphne, Hypercorn, uWSGI и т. д. — серверами приложений. + * Если Вы сравниваете Uvicorn, сравнивайте его с Daphne, Hypercorn, uWSGI и т.д. — серверами приложений. * **Starlette**: * Будет на следующем месте по производительности после Uvicorn. Фактически Starlette запускается под управлением Uvicorn, поэтому он может быть только «медленнее» Uvicorn из‑за выполнения большего объёма кода. - * Зато он предоставляет Вам инструменты для создания простых веб‑приложений с маршрутизацией по путям и т. п. - * Если Вы сравниваете Starlette, сравнивайте его с Sanic, Flask, Django и т. д. — веб‑фреймворками (или микрофреймворками). + * Зато он предоставляет Вам инструменты для создания простых веб‑приложений с маршрутизацией по путям и т.п. + * Если Вы сравниваете Starlette, сравнивайте его с Sanic, Flask, Django и т.д. — веб‑фреймворками (или микрофреймворками). * **FastAPI**: * Точно так же, как Starlette использует Uvicorn и не может быть быстрее него, **FastAPI** использует Starlette, поэтому не может быть быстрее его. * FastAPI предоставляет больше возможностей поверх Starlette — те, которые почти всегда нужны при создании API, такие как валидация и сериализация данных. В довесок Вы ещё и получаете автоматическую документацию (автоматическая документация даже не увеличивает накладные расходы при работе приложения, так как она создаётся при запуске). - * Если бы Вы не использовали FastAPI, а использовали Starlette напрямую (или другой инструмент вроде Sanic, Flask, Responder и т. д.), Вам пришлось бы самостоятельно реализовать валидацию и сериализацию данных. То есть, в итоге, Ваше приложение имело бы такие же накладные расходы, как если бы оно было создано с использованием FastAPI. И во многих случаях валидация и сериализация данных представляют собой самый большой объём кода, написанного в приложениях. + * Если бы Вы не использовали FastAPI, а использовали Starlette напрямую (или другой инструмент вроде Sanic, Flask, Responder и т.д.), Вам пришлось бы самостоятельно реализовать валидацию и сериализацию данных. То есть, в итоге, Ваше приложение имело бы такие же накладные расходы, как если бы оно было создано с использованием FastAPI. И во многих случаях валидация и сериализация данных представляют собой самый большой объём кода, написанного в приложениях. * Таким образом, используя FastAPI, Вы экономите время разработки, уменьшаете количество ошибок, строк кода и, вероятно, получите ту же производительность (или лучше), как и если бы не использовали его (поскольку Вам пришлось бы реализовать все его возможности в своём коде). * Если Вы сравниваете FastAPI, сравнивайте его с фреймворком веб‑приложений (или набором инструментов), который обеспечивает валидацию данных, сериализацию и документацию, такими как Flask-apispec, NestJS, Molten и им подобные. Фреймворки с интегрированной автоматической валидацией данных, сериализацией и документацией. diff --git a/docs/ru/docs/deployment/concepts.md b/docs/ru/docs/deployment/concepts.md index 207d1604d..173dbb962 100644 --- a/docs/ru/docs/deployment/concepts.md +++ b/docs/ru/docs/deployment/concepts.md @@ -27,13 +27,13 @@ В [предыдущей главе про HTTPS](https.md){.internal-link target=_blank} мы разобрались, как HTTPS обеспечивает шифрование для вашего API. -Также мы увидели, что HTTPS обычно обеспечивает компонент, **внешний** по отношению к серверу вашего приложения — **TLS Termination Proxy**. +Также мы увидели, что HTTPS обычно обеспечивает компонент, **внешний** по отношению к серверу вашего приложения — **прокси-сервер TSL-терминации**. И должен быть компонент, отвечающий за **обновление HTTPS‑сертификатов** — это может быть тот же самый компонент или отдельный. ### Примеры инструментов для HTTPS { #example-tools-for-https } -Некоторые инструменты, которые можно использовать как TLS Termination Proxy: +Некоторые инструменты, которые можно использовать как прокси-сервер TSL-терминации: * Traefik * Автоматически обновляет сертификаты ✨ @@ -47,7 +47,7 @@ * С внешним компонентом (например, cert-manager) для обновления сертификатов * Обрабатывается внутри облачного провайдера как часть его услуг (см. ниже 👇) -Другой вариант — использовать **облачный сервис**, который возьмёт на себя больше задач, включая настройку HTTPS. Там могут быть ограничения или дополнительная стоимость и т.п., но в таком случае вам не придётся самим настраивать TLS Termination Proxy. +Другой вариант — использовать **облачный сервис**, который возьмёт на себя больше задач, включая настройку HTTPS. Там могут быть ограничения или дополнительная стоимость и т.п., но в таком случае вам не придётся самим настраивать прокси-сервер TSL-терминации. В следующих главах я покажу конкретные примеры. @@ -214,7 +214,7 @@ Процесс‑менеджер, вероятно, будет тем, кто слушает **порт** на IP. И он будет передавать всю коммуникацию воркер‑процессам. -Эти воркеры будут запускать ваше приложение, выполнять основные вычисления для получения **запроса** и возврата **ответа**, и загружать всё, что вы кладёте в переменные, в RAM. +Эти воркеры будут запускать ваше приложение, выполнять основные вычисления для получения **HTTP‑запроса** и возврата **HTTP‑ответа**, и загружать всё, что вы кладёте в переменные, в RAM. @@ -289,7 +289,7 @@ Ваш сервер(а) — это **ресурс**, который ваши программы могут потреблять или **использовать**: время вычислений на CPU и доступную оперативную память (RAM). -Какую долю системных ресурсов вы хотите потреблять/использовать? Можно подумать «немного», но на практике вы, скорее всего, захотите потреблять **максимум без падений**. +Какую долю системных ресурсов вы хотите потреблять/использовать? Можно подумать «немного», но на практике вы, вероятно, захотите потреблять **максимум без падений**. Если вы платите за 3 сервера, но используете лишь малую часть их RAM и CPU, вы, вероятно, **тратите деньги впустую** 💸 и **электроэнергию серверов** 🌎 и т.п. diff --git a/docs/ru/docs/deployment/docker.md b/docs/ru/docs/deployment/docker.md index 9e8562be7..791057fe5 100644 --- a/docs/ru/docs/deployment/docker.md +++ b/docs/ru/docs/deployment/docker.md @@ -14,7 +14,7 @@ Предпросмотр Dockerfile 👀 ```Dockerfile -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -166,7 +166,7 @@ def read_item(item_id: int, q: str | None = None): ```{ .dockerfile .annotate } # (1)! -FROM python:3.9 +FROM python:3.14 # (2)! WORKDIR /code @@ -273,9 +273,9 @@ CMD fastapi run app/main.py --port 80 └── requirements.txt ``` -#### За прокси-сервером TLS терминации { #behind-a-tls-termination-proxy } +#### За прокси-сервером TSL-терминации { #behind-a-tls-termination-proxy } -Если вы запускаете контейнер за прокси-сервером завершения TLS (балансировщиком нагрузки), таким как Nginx или Traefik, добавьте опцию `--proxy-headers`. Это сообщит Uvicorn (через FastAPI CLI), что приложение работает за HTTPS и можно доверять соответствующим заголовкам. +Если вы запускаете контейнер за прокси-сервером TSL-терминации (балансировщиком нагрузки), таким как Nginx или Traefik, добавьте опцию `--proxy-headers`. Это сообщит Uvicorn (через FastAPI CLI), что приложение работает за HTTPS и можно доверять соответствующим заголовкам. ```Dockerfile CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"] @@ -390,7 +390,7 @@ $ docker run -d --name mycontainer -p 80:80 myimage Тогда в `Dockerfile` нужно изменить пути копирования: ```{ .dockerfile .annotate hl_lines="10 13" } -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -454,7 +454,7 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] ## Репликация — количество процессов { #replication-number-of-processes } -Если у вас есть кластер машин с **Kubernetes**, Docker Swarm Mode, Nomad или другой похожей системой для управления распределёнными контейнерами на нескольких машинах, скорее всего вы будете **управлять репликацией** на **уровне кластера**, а не использовать **менеджер процессов** (например, Uvicorn с воркерами) в каждом контейнере. +Если у вас есть кластер машин с **Kubernetes**, Docker Swarm Mode, Nomad или другой похожей системой для управления распределёнными контейнерами на нескольких машинах, скорее всего вы будете **управлять репликацией** на **уровне кластера**, а не использовать **менеджер процессов** (например, Uvicorn с воркерами) в каждом контейнере. Одна из таких систем управления распределёнными контейнерами, как Kubernetes, обычно имеет встроенный способ управлять **репликацией контейнеров**, поддерживая **балансировку нагрузки** для входящих запросов — всё это на **уровне кластера**. @@ -462,17 +462,17 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] ### Балансировщик нагрузки { #load-balancer } -При использовании контейнеров обычно есть компонент, **слушающий главный порт**. Это может быть другой контейнер — **прокси завершения TLS** для обработки **HTTPS** или похожий инструмент. +При использовании контейнеров обычно есть компонент, **слушающий главный порт**. Это может быть другой контейнер — **прокси-сервер TSL-терминации** для обработки **HTTPS** или похожий инструмент. Поскольку этот компонент принимает **нагрузку** запросов и распределяет её между воркерами **сбалансированно**, его часто называют **балансировщиком нагрузки**. /// tip | Подсказка -Тот же компонент **прокси завершения TLS**, который обрабатывает HTTPS, скорее всего также будет **балансировщиком нагрузки**. +Тот же компонент **прокси-сервер TSL-терминации**, который обрабатывает HTTPS, скорее всего также будет **балансировщиком нагрузки**. /// -При работе с контейнерами система, которую вы используете для запуска и управления ими, уже имеет внутренние средства для передачи **сетевого взаимодействия** (например, HTTP-запросов) от **балансировщика нагрузки** (который также может быть **прокси завершения TLS**) к контейнеру(-ам) с вашим приложением. +При работе с контейнерами система, которую вы используете для запуска и управления ими, уже имеет внутренние средства для передачи **сетевого взаимодействия** (например, HTTP-запросов) от **балансировщика нагрузки** (который также может быть **прокси-сервером TSL-терминации**) к контейнеру(-ам) с вашим приложением. ### Один балансировщик — несколько контейнеров-воркеров { #one-load-balancer-multiple-worker-containers } @@ -499,7 +499,7 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] В таких случаях вы можете использовать опцию командной строки `--workers`, чтобы указать нужное количество воркеров: ```{ .dockerfile .annotate } -FROM python:3.9 +FROM python:3.14 WORKDIR /code diff --git a/docs/ru/docs/deployment/https.md b/docs/ru/docs/deployment/https.md index 05a03255e..ffeccfd7d 100644 --- a/docs/ru/docs/deployment/https.md +++ b/docs/ru/docs/deployment/https.md @@ -65,7 +65,7 @@ Чаще всего всё начинается с **приобретения** **имени домена**. Затем вы настраиваете его на DNS‑сервере (возможно, у того же облачного провайдера). -Скорее всего, вы получите облачный сервер (виртуальную машину) или что-то подобное, и у него будет постоянный **публичный IP-адрес**. +Скорее всего, вы получите облачный сервер (виртуальную машину) или что-то подобное, и у него будет постоянный **публичный IP-адрес**. На DNS‑сервере(ах) вы настроите запись («`A record`» - запись типа A), указывающую, что **ваш домен** должен указывать на публичный **IP‑адрес вашего сервера**. diff --git a/docs/ru/docs/deployment/index.md b/docs/ru/docs/deployment/index.md index ffb77641d..7e735593b 100644 --- a/docs/ru/docs/deployment/index.md +++ b/docs/ru/docs/deployment/index.md @@ -18,6 +18,6 @@ Например, мы, команда, стоящая за FastAPI, создали **FastAPI Cloud**, чтобы сделать развёртывание приложений FastAPI в облаке как можно более простым и прямолинейным, с тем же удобством для разработчика, что и при работе с FastAPI. -В этом блоке я покажу вам некоторые из основных концепций, которые вы, вероятно, должны иметь в виду при развертывании приложения **FastAPI** (хотя большинство из них применимо к любому другому типу веб-приложений). +Я покажу вам некоторые из основных концепций, которые вы, вероятно, должны иметь в виду при развертывании приложения **FastAPI** (хотя большинство из них применимо к любому другому типу веб-приложений). В последующих разделах вы узнаете больше деталей и методов, необходимых для этого. ✨ diff --git a/docs/ru/docs/deployment/versions.md b/docs/ru/docs/deployment/versions.md index 58d5aa110..4195d689f 100644 --- a/docs/ru/docs/deployment/versions.md +++ b/docs/ru/docs/deployment/versions.md @@ -1,12 +1,12 @@ # О версиях FastAPI { #about-fastapi-versions } -**FastAPI** уже используется в продакшене во многих приложениях и системах. Покрытие тестами поддерживается на уровне 100%. Но его разработка всё ещё движется быстрыми темпами. +**FastAPI** уже используется в продакшн во многих приложениях и системах. Покрытие тестами поддерживается на уровне 100%. Но его разработка всё ещё движется быстрыми темпами. Часто добавляются новые функции, регулярно исправляются баги, код продолжает постоянно совершенствоваться. По указанным причинам текущие версии до сих пор `0.x.x`. Это говорит о том, что каждая версия может содержать обратно несовместимые изменения, следуя Семантическому версионированию. -Уже сейчас вы можете создавать приложения в продакшене, используя **FastAPI** (и скорее всего так и делаете), главное убедиться в том, что вы используете версию, которая корректно работает с вашим кодом. +Уже сейчас вы можете создавать приложения в продакшн, используя **FastAPI** (и скорее всего так и делаете), главное убедиться в том, что вы используете версию, которая корректно работает с вашим кодом. ## Закрепите вашу версию `fastapi` { #pin-your-fastapi-version } diff --git a/docs/ru/docs/environment-variables.md b/docs/ru/docs/environment-variables.md index 6291b79d2..759127420 100644 --- a/docs/ru/docs/environment-variables.md +++ b/docs/ru/docs/environment-variables.md @@ -161,7 +161,7 @@ Hello World from Python Эти переменные окружения могут работать только с **текстовыми строками**, поскольку они являются внешними по отношению к Python и должны быть совместимы с другими программами и остальной системой (и даже с различными операционными системами, такими как Linux, Windows, macOS). -Это означает, что **любое значение**, считанное в Python из переменной окружения, **будет `str`**, и любое преобразование к другому типу или любая проверка должны быть выполнены в коде. +Это означает, что **любое значение**, считанное в Python из переменной окружения, **будет `str`**, и любое преобразование к другому типу или любая валидация должны быть выполнены в коде. Подробнее об использовании переменных окружения для работы с **настройками приложения** вы узнаете в [Расширенное руководство пользователя - Настройки и переменные среды](./advanced/settings.md){.internal-link target=_blank}. diff --git a/docs/ru/docs/fastapi-cli.md b/docs/ru/docs/fastapi-cli.md index 72cf55e7b..a46e0053e 100644 --- a/docs/ru/docs/fastapi-cli.md +++ b/docs/ru/docs/fastapi-cli.md @@ -52,7 +52,7 @@ FastAPI CLI берет путь к вашей Python-программе (нап Для работы в режиме продакшн вместо `fastapi dev` нужно использовать `fastapi run`. 🚀 -Внутри **FastAPI CLI** используется Uvicorn, высокопроизводительный, готовый к работе в продакшне ASGI-сервер. 😎 +Внутри **FastAPI CLI** используется Uvicorn, высокопроизводительный, готовый к работе в продакшн ASGI-сервер. 😎 ## `fastapi dev` { #fastapi-dev } diff --git a/docs/ru/docs/features.md b/docs/ru/docs/features.md index 703ff951e..0bc3dbb2d 100644 --- a/docs/ru/docs/features.md +++ b/docs/ru/docs/features.md @@ -6,7 +6,7 @@ ### Основано на открытых стандартах { #based-on-open-standards } -* OpenAPI для создания API, включая объявления операций пути, параметров, тел запросов, безопасности и т. д. +* OpenAPI для создания API, включая объявления операций пути, параметров, тел запросов, безопасности и т.д. * Автоматическая документация моделей данных с помощью JSON Schema (так как сама спецификация OpenAPI основана на JSON Schema). * Разработан вокруг этих стандартов, после тщательного их изучения. Это не дополнительная надстройка поверх. * Это также позволяет использовать автоматическую **генерацию клиентского кода** на многих языках. @@ -107,7 +107,7 @@ FastAPI имеет продуманные значения **по умолчан * Объекты JSON (`dict`). * Массив JSON (`list`) с определёнными типами элементов. * Строковые (`str`) поля с ограничением минимальной и максимальной длины. - * Числа (`int`, `float`) с минимальными и максимальными значениями и т. п. + * Числа (`int`, `float`) с минимальными и максимальными значениями и т.п. * Проверка для более экзотических типов, таких как: * URL. @@ -126,24 +126,24 @@ FastAPI имеет продуманные значения **по умолчан * HTTP Basic. * **OAuth2** (также с **токенами JWT**). Ознакомьтесь с руководством [OAuth2 с JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. * Ключи API в: - * Заголовках. + * HTTP-заголовках. * Параметрах запросов. * Cookies и т.п. Вдобавок все функции безопасности от Starlette (включая **сессионные cookies**). -Все инструменты и компоненты спроектированы для многократного использования и легко интегрируются с вашими системами, хранилищами данных, реляционными и NoSQL базами данных и т. д. +Все инструменты и компоненты спроектированы для многократного использования и легко интегрируются с вашими системами, хранилищами данных, реляционными и NoSQL базами данных и т.д. ### Внедрение зависимостей { #dependency-injection } -FastAPI включает в себя чрезвычайно простую в использовании, но чрезвычайно мощную систему Внедрения зависимостей. +FastAPI включает в себя чрезвычайно простую в использовании, но чрезвычайно мощную систему Внедрения зависимостей. * Даже зависимости могут иметь зависимости, создавая иерархию или **«граф» зависимостей**. * Всё **автоматически обрабатывается** фреймворком. * Все зависимости могут запрашивать данные из запросов и **дополнять операции пути** ограничениями и автоматической документацией. * **Автоматическая проверка** даже для параметров *операций пути*, определённых в зависимостях. -* Поддержка сложных систем аутентификации пользователей, **соединений с базами данных** и т. д. -* **Никаких компромиссов** с базами данных, интерфейсами и т. д. Но при этом — лёгкая интеграция со всеми ними. +* Поддержка сложных систем аутентификации пользователей, **соединений с базами данных** и т.д. +* **Никаких компромиссов** с базами данных, интерфейсами и т.д. Но при этом — лёгкая интеграция со всеми ними. ### Нет ограничений на "Плагины" { #unlimited-plug-ins } @@ -153,8 +153,8 @@ FastAPI включает в себя чрезвычайно простую в и ### Проверен { #tested } -* 100% покрытие тестами. -* 100% аннотирование типов в кодовой базе. +* 100% покрытие тестами. +* 100% аннотирование типов в кодовой базе. * Используется в продакшн‑приложениях. ## Возможности Starlette { #starlette-features } @@ -179,7 +179,7 @@ FastAPI включает в себя чрезвычайно простую в и **FastAPI** полностью совместим с (и основан на) Pydantic. Поэтому любой дополнительный код Pydantic, который у вас есть, также будет работать. -Включая внешние библиотеки, также основанные на Pydantic, такие как ORM’ы, ODM’ы для баз данных. +Включая внешние библиотеки, также основанные на Pydantic, такие как ORM’ы, ODM’ы для баз данных. Это также означает, что во многих случаях вы можете передавать тот же объект, который получили из запроса, **непосредственно в базу данных**, так как всё проверяется автоматически. @@ -190,10 +190,10 @@ FastAPI включает в себя чрезвычайно простую в и * **Никакой нервотрёпки**: * Не нужно изучать новые схемы в микроязыках. * Если вы знаете типы в Python, вы знаете, как использовать Pydantic. -* Прекрасно сочетается с вашим **IDE/linter/мозгом**: +* Прекрасно сочетается с вашим **IDE/линтер/мозгом**: * Потому что структуры данных pydantic — это всего лишь экземпляры классов, определённых вами; автозавершение, проверка кода, mypy и ваша интуиция — всё будет работать с вашими валидированными данными. * Валидация **сложных структур**: - * Использование иерархических моделей Pydantic; `List`, `Dict` и т. п. из модуля `typing` (входит в стандартную библиотеку Python). + * Использование иерархических моделей Pydantic; `List`, `Dict` и т.п. из модуля `typing` (входит в стандартную библиотеку Python). * Валидаторы позволяют чётко и легко определять, проверять и документировать сложные схемы данных в виде JSON Schema. * У вас могут быть глубоко **вложенные объекты JSON**, и все они будут проверены и аннотированы. * **Расширяемость**: diff --git a/docs/ru/docs/history-design-future.md b/docs/ru/docs/history-design-future.md index 9cdd53376..e2395fe8b 100644 --- a/docs/ru/docs/history-design-future.md +++ b/docs/ru/docs/history-design-future.md @@ -30,7 +30,7 @@ ## Исследования { #investigation } -Благодаря опыту использования существующих альтернатив, мы с коллегами изучили их основные идеи и скомбинировали собранные знания наилучшим образом. +Используя все существовавшие ранее альтернативы, я получил возможность у каждой из них чему-то научиться, позаимствовать идеи и объединить их наилучшим образом для себя и для команд разработчиков, с которыми я работал. Например, стало ясно, что необходимо брать за основу стандартные аннотации типов Python. @@ -44,13 +44,13 @@ Я проверил несколько идей на самых популярных редакторах кода: PyCharm, VS Code, редакторы на базе Jedi. -Данные по редакторам я взял из опроса Python-разработчиков, который охватывает около 80% пользователей. +Согласно последнему опросу Python-разработчиков, который охватывает около 80% пользователей. Это означает, что **FastAPI** был специально проверен на редакторах, используемых 80% Python-разработчиками. И поскольку большинство других редакторов, как правило, работают аналогичным образом, все его преимущества должны работать практически для всех редакторов. Таким образом, я смог найти наилучшие способы сократить дублирование кода, обеспечить повсеместное автозавершение, проверку типов и ошибок и т.д. -И все это, чтобы все пользователи могли получать наилучший опыт разработки. +И все это, чтобы все разработчики могли получать наилучший опыт разработки. ## Зависимости { #requirements } @@ -58,7 +58,7 @@ По моим предложениям был изменён код этого фреймворка, чтобы сделать его полностью совместимым с JSON Schema, поддержать различные способы определения ограничений и улучшить поддержку в редакторах кода (проверки типов, автозавершение) на основе тестов в нескольких редакторах. -В то же время, я принимал участие в разработке **Starlette**, ещё один из основных компонентов FastAPI. +Во время разработки я также внес вклад в **Starlette**, другую ключевую зависимость. ## Разработка { #development } diff --git a/docs/ru/docs/how-to/authentication-error-status-code.md b/docs/ru/docs/how-to/authentication-error-status-code.md index 5675cecc5..596563c54 100644 --- a/docs/ru/docs/how-to/authentication-error-status-code.md +++ b/docs/ru/docs/how-to/authentication-error-status-code.md @@ -8,7 +8,7 @@ Например, вы можете создать подкласс `HTTPBearer`, который будет возвращать ошибку `403 Forbidden` вместо стандартной `401 Unauthorized`: -{* ../../docs_src/authentication_error_status_code/tutorial001_an_py39.py hl[9:13] *} +{* ../../docs_src/authentication_error_status_code/tutorial001_an_py310.py hl[9:13] *} /// tip | Совет diff --git a/docs/ru/docs/how-to/conditional-openapi.md b/docs/ru/docs/how-to/conditional-openapi.md index d0845b91e..6efa30608 100644 --- a/docs/ru/docs/how-to/conditional-openapi.md +++ b/docs/ru/docs/how-to/conditional-openapi.md @@ -4,9 +4,9 @@ ## О безопасности, API и документации { #about-security-apis-and-docs } -Скрытие пользовательских интерфейсов документации в продакшн *не должно* быть способом защиты вашего API. +Скрытие пользовательских интерфейсов документации в продакшн не должно быть способом защиты вашего API. -Это не добавляет дополнительной безопасности вашему API, *операции пути* (обработчики пути) всё равно будут доступны по своим путям. +Это не добавляет дополнительной безопасности вашему API, операции пути (обработчики пути) всё равно будут доступны по своим путям. Если в вашем коде есть уязвимость, она всё равно останется. @@ -29,7 +29,7 @@ Например: -{* ../../docs_src/conditional_openapi/tutorial001_py39.py hl[6,11] *} +{* ../../docs_src/conditional_openapi/tutorial001_py310.py hl[6,11] *} Здесь мы объявляем настройку `openapi_url` с тем же значением по умолчанию — `"/openapi.json"`. diff --git a/docs/ru/docs/how-to/configure-swagger-ui.md b/docs/ru/docs/how-to/configure-swagger-ui.md index b3b1c1ba6..f4f2a0e54 100644 --- a/docs/ru/docs/how-to/configure-swagger-ui.md +++ b/docs/ru/docs/how-to/configure-swagger-ui.md @@ -18,7 +18,7 @@ FastAPI преобразует эти настройки в **JSON**, чтобы Но вы можете отключить её, установив `syntaxHighlight` в `False`: -{* ../../docs_src/configure_swagger_ui/tutorial001_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *} …и после этого Swagger UI больше не будет показывать подсветку синтаксиса: @@ -28,7 +28,7 @@ FastAPI преобразует эти настройки в **JSON**, чтобы Аналогично вы можете задать тему подсветки синтаксиса с ключом "syntaxHighlight.theme" (обратите внимание, что посередине стоит точка): -{* ../../docs_src/configure_swagger_ui/tutorial002_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *} Эта настройка изменит цветовую тему подсветки синтаксиса: @@ -46,7 +46,7 @@ FastAPI включает некоторые параметры конфигур Например, чтобы отключить `deepLinking`, можно передать такие настройки в `swagger_ui_parameters`: -{* ../../docs_src/configure_swagger_ui/tutorial003_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial003_py310.py hl[3] *} ## Другие параметры Swagger UI { #other-swagger-ui-parameters } 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 f524911e6..e3c31b32c 100644 --- a/docs/ru/docs/how-to/custom-docs-ui-assets.md +++ b/docs/ru/docs/how-to/custom-docs-ui-assets.md @@ -18,7 +18,7 @@ Чтобы отключить её, установите их URL в значение `None` при создании вашего приложения `FastAPI`: -{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[8] *} +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[8] *} ### Подключить пользовательскую документацию { #include-the-custom-docs } @@ -34,7 +34,7 @@ Аналогично и для ReDoc... -{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[2:6,11:19,22:24,27:33] *} +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[2:6,11:19,22:24,27:33] *} /// tip | Совет @@ -50,7 +50,7 @@ Swagger UI сделает это за вас «за кулисами», но д Чтобы убедиться, что всё работает, создайте *операцию пути*: -{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[36:38] *} +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[36:38] *} ### Тестирование { #test-it } @@ -118,7 +118,7 @@ Swagger UI сделает это за вас «за кулисами», но д * Импортируйте `StaticFiles`. * Смонтируйте экземпляр `StaticFiles()` в определённый путь. -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[7,11] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[7,11] *} ### Протестируйте статические файлы { #test-the-static-files } @@ -144,7 +144,7 @@ Swagger UI сделает это за вас «за кулисами», но д Чтобы отключить её, установите их URL в значение `None` при создании вашего приложения `FastAPI`: -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[9] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[9] *} ### Подключить пользовательскую документацию со статическими файлами { #include-the-custom-docs-for-static-files } @@ -160,7 +160,7 @@ Swagger UI сделает это за вас «за кулисами», но д Аналогично и для ReDoc... -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[2:6,14:22,25:27,30:36] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[2:6,14:22,25:27,30:36] *} /// tip | Совет @@ -176,7 +176,7 @@ Swagger UI сделает это за вас «за кулисами», но д Чтобы убедиться, что всё работает, создайте *операцию пути*: -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[39:41] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[39:41] *} ### Тестирование UI со статическими файлами { #test-static-files-ui } diff --git a/docs/ru/docs/how-to/extending-openapi.md b/docs/ru/docs/how-to/extending-openapi.md index 1d69cbdb3..197a1790a 100644 --- a/docs/ru/docs/how-to/extending-openapi.md +++ b/docs/ru/docs/how-to/extending-openapi.md @@ -24,7 +24,7 @@ * `version`: Версия вашего API, например `2.5.0`. * `openapi_version`: Версия используемой спецификации OpenAPI. По умолчанию — последняя: `3.1.0`. * `summary`: Краткое описание API. -* `description`: Описание вашего API; может включать Markdown и будет отображается в документации. +* `description`: Описание вашего API; может включать Markdown и будет отображаться в документации. * `routes`: Список маршрутов — это каждая зарегистрированная *операция пути*. Берутся из `app.routes`. /// info | Информация @@ -43,19 +43,19 @@ Сначала напишите приложение **FastAPI** как обычно: -{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[1,4,7:9] *} +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[1,4,7:9] *} ### Сгенерируйте схему OpenAPI { #generate-the-openapi-schema } Затем используйте ту же вспомогательную функцию для генерации схемы OpenAPI внутри функции `custom_openapi()`: -{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[2,15:21] *} +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[2,15:21] *} ### Измените схему OpenAPI { #modify-the-openapi-schema } Теперь можно добавить расширение ReDoc, добавив кастомный `x-logo` в «объект» `info` в схеме OpenAPI: -{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[22:24] *} +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[22:24] *} ### Кэшируйте схему OpenAPI { #cache-the-openapi-schema } @@ -65,13 +65,13 @@ Она будет создана один раз, а затем тот же кэшированный вариант будет использоваться для последующих запросов. -{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[13:14,25:26] *} +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[13:14,25:26] *} ### Переопределите метод { #override-the-method } Теперь вы можете заменить метод `.openapi()` на вашу новую функцию. -{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[29] *} +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[29] *} ### Проверьте { #check-it } diff --git a/docs/ru/docs/how-to/graphql.md b/docs/ru/docs/how-to/graphql.md index 50c321e7d..9e28d6182 100644 --- a/docs/ru/docs/how-to/graphql.md +++ b/docs/ru/docs/how-to/graphql.md @@ -35,7 +35,7 @@ Вот небольшой пример того, как можно интегрировать Strawberry с FastAPI: -{* ../../docs_src/graphql_/tutorial001_py39.py hl[3,22,25] *} +{* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *} Подробнее о Strawberry можно узнать в документации Strawberry. diff --git a/docs/ru/docs/how-to/index.md b/docs/ru/docs/how-to/index.md index 228c125dd..75e7fff26 100644 --- a/docs/ru/docs/how-to/index.md +++ b/docs/ru/docs/how-to/index.md @@ -1,13 +1,13 @@ # Как сделать — Рецепты { #how-to-recipes } -Здесь вы найдете разные рецепты и руководства «как сделать» по различным темам. +Здесь вы найдете разные рецепты и руководства «как сделать» по **различным темам**. -Большинство из этих идей более-менее независимы, и в большинстве случаев вам стоит изучать их только если они напрямую относятся к вашему проекту. +Большинство из этих идей более-менее **независимы**, и в большинстве случаев вам стоит изучать их только если они напрямую относятся к **вашему проекту**. Если что-то кажется интересным и полезным для вашего проекта, смело изучайте; в противном случае, вероятно, можно просто пропустить. /// tip | Совет -Если вы хотите изучить FastAPI структурированно (рекомендуется), вместо этого читайте [Учебник — Руководство пользователя](../tutorial/index.md){.internal-link target=_blank} по главам. +Если вы хотите **изучить FastAPI** структурированно (рекомендуется), вместо этого читайте [Учебник — Руководство пользователя](../tutorial/index.md){.internal-link target=_blank} по главам. /// diff --git a/docs/ru/docs/index.md b/docs/ru/docs/index.md index b1a0c9a2e..877014a08 100644 --- a/docs/ru/docs/index.md +++ b/docs/ru/docs/index.md @@ -40,7 +40,7 @@ FastAPI — это современный, быстрый (высокопрои * **Скорость**: Очень высокая производительность, на уровне **NodeJS** и **Go** (благодаря Starlette и Pydantic). [Один из самых быстрых доступных фреймворков Python](#performance). * **Быстрота разработки**: Увеличьте скорость разработки фич примерно на 200–300%. * * **Меньше ошибок**: Сократите примерно на 40% количество ошибок, вызванных человеком (разработчиком). * -* **Интуитивность**: Отличная поддержка редактора кода. Автозавершение везде. Меньше времени на отладку. +* **Интуитивность**: Отличная поддержка редактора кода. Автозавершение везде. Меньше времени на отладку. * **Простота**: Разработан так, чтобы его было легко использовать и осваивать. Меньше времени на чтение документации. * **Краткость**: Минимизируйте дублирование кода. Несколько возможностей из каждого объявления параметров. Меньше ошибок. * **Надежность**: Получите код, готовый к продакшн. С автоматической интерактивной документацией. @@ -127,7 +127,7 @@ FastAPI — это современный, быстрый (высокопрои -Если вы создаёте приложение CLI для использования в терминале вместо веб-API, посмотрите **Typer**. +Если вы создаёте приложение CLI для использования в терминале вместо веб-API, посмотрите **Typer**. **Typer** — младший брат FastAPI. И он задуман как **FastAPI для CLI**. ⌨️ 🚀 @@ -368,7 +368,7 @@ item: Item * Валидацию данных: * Автоматические и понятные ошибки, когда данные некорректны. * Валидацию даже для глубоко вложенных объектов JSON. -* Преобразование входных данных: из сети в данные и типы Python. Чтение из: +* Преобразование входных данных: из сети в данные и типы Python. Чтение из: * JSON. * Параметров пути. * Параметров запроса. @@ -376,7 +376,7 @@ item: Item * HTTP-заголовков. * Форм. * Файлов. -* Преобразование выходных данных: из данных и типов Python в данные сети (например, JSON): +* Преобразование выходных данных: из данных и типов Python в данные сети (например, JSON): * Преобразование типов Python (`str`, `int`, `float`, `bool`, `list` и т.д.). * Объекты `datetime`. * Объекты `UUID`. @@ -439,7 +439,7 @@ item: Item * Объявление **параметров** из других источников: **HTTP-заголовки**, **cookies**, **поля формы** и **файлы**. * Как задать **ограничения валидации** вроде `maximum_length` или `regex`. -* Очень мощную и простую в использовании систему **внедрения зависимостей**. +* Очень мощную и простую в использовании систему **внедрения зависимостей**. * Безопасность и аутентификацию, включая поддержку **OAuth2** с **JWT токенами** и **HTTP Basic** аутентификацию. * Более продвинутые (но столь же простые) приёмы объявления **глубоко вложенных JSON-моделей** (спасибо Pydantic). * Интеграцию **GraphQL** с Strawberry и другими библиотеками. @@ -524,7 +524,7 @@ FastAPI зависит от Pydantic и Starlette. * httpx — обязателен, если вы хотите использовать `TestClient`. * jinja2 — обязателен, если вы хотите использовать конфигурацию шаблонов по умолчанию. -* python-multipart - обязателен, если вы хотите поддерживать «парсинг» форм через `request.form()`. +* python-multipart - обязателен, если вы хотите поддерживать «парсинг» форм через `request.form()`. Используется FastAPI: diff --git a/docs/ru/docs/project-generation.md b/docs/ru/docs/project-generation.md index dbedf76fe..8155457e3 100644 --- a/docs/ru/docs/project-generation.md +++ b/docs/ru/docs/project-generation.md @@ -18,7 +18,7 @@ - 🤖 Автоматически сгенерированный фронтенд‑клиент. - 🧪 [Playwright](https://playwright.dev) для End‑to‑End тестирования. - 🦇 Поддержка тёмной темы. -- 🐋 [Docker Compose](https://www.docker.com) для разработки и продакшна. +- 🐋 [Docker Compose](https://www.docker.com) для разработки и продакшн. - 🔒 Безопасное хэширование паролей по умолчанию. - 🔑 Аутентификация по JWT‑токенам. - 📫 Восстановление пароля по электронной почте. diff --git a/docs/ru/docs/python-types.md b/docs/ru/docs/python-types.md index ae4a1e2b7..95153c388 100644 --- a/docs/ru/docs/python-types.md +++ b/docs/ru/docs/python-types.md @@ -2,7 +2,7 @@ Python поддерживает необязательные «подсказки типов» (их также называют «аннотациями типов»). -Эти **«подсказки типов»** или аннотации — это специальный синтаксис, позволяющий объявлять тип переменной. +Эти **«подсказки типов»** или аннотации — это специальный синтаксис, позволяющий объявлять тип переменной. Объявляя типы для ваших переменных, редакторы кода и инструменты смогут лучше вас поддерживать. @@ -22,7 +22,7 @@ Python поддерживает необязательные «подсказк Давайте начнем с простого примера: -{* ../../docs_src/python_types/tutorial001_py39.py *} +{* ../../docs_src/python_types/tutorial001_py310.py *} Вызов этой программы выводит: @@ -34,9 +34,9 @@ John Doe * Принимает `first_name` и `last_name`. * Преобразует первую букву каждого значения в верхний регистр с помощью `title()`. -* Соединяет их пробелом посередине. +* Соединяет их пробелом посередине. -{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial001_py310.py hl[2] *} ### Отредактируем пример { #edit-it } @@ -78,7 +78,7 @@ John Doe Это и есть «подсказки типов»: -{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *} Это не то же самое, что объявление значений по умолчанию, как, например: @@ -106,7 +106,7 @@ John Doe Посмотрите на эту функцию — у неё уже есть подсказки типов: -{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial003_py310.py hl[1] *} Так как редактор кода знает типы переменных, вы получаете не только автозавершение, но и проверки ошибок: @@ -114,7 +114,7 @@ John Doe Теперь вы знаете, что нужно исправить — преобразовать `age` в строку с помощью `str(age)`: -{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial004_py310.py hl[2] *} ## Объявление типов { #declaring-types } @@ -133,29 +133,32 @@ John Doe * `bool` * `bytes` -{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial005_py310.py hl[1] *} -### Generic-типы с параметрами типов { #generic-types-with-type-parameters } +### Модуль `typing` { #typing-module } -Есть структуры данных, которые могут содержать другие значения, например, `dict`, `list`, `set` и `tuple`. И внутренние значения тоже могут иметь свой тип. +Для некоторых дополнительных сценариев может понадобиться импортировать что-то из стандартного модуля `typing`. Например, когда вы хотите объявить, что что-то имеет «любой тип», можно использовать `Any` из `typing`: -Такие типы, которые содержат внутренние типы, называют «**generic**»-типами. И их можно объявлять, в том числе с указанием внутренних типов. +```python +from typing import Any -Чтобы объявлять эти типы и их внутренние типы, вы можете использовать стандартный модуль Python `typing`. Он существует специально для поддержки подсказок типов. -#### Новые версии Python { #newer-versions-of-python } +def some_function(data: Any): + print(data) +``` -Синтаксис с использованием `typing` **совместим** со всеми версиями, от Python 3.6 до самых новых, включая Python 3.9, Python 3.10 и т.д. +### Generic-типы { #generic-types } -По мере развития Python **новые версии** получают улучшенную поддержку этих аннотаций типов, и во многих случаях вам даже не нужно импортировать и использовать модуль `typing`, чтобы объявлять аннотации типов. +Некоторые типы могут принимать «параметры типов» в квадратных скобках, чтобы определить их внутренние типы. Например, «список строк» объявляется как `list[str]`. -Если вы можете выбрать более свежую версию Python для проекта, вы получите дополнительную простоту. +Такие типы, которые принимают параметры типов, называются **Generic-типами** или **Generics**. -Во всей документации есть примеры, совместимые с каждой версией Python (когда есть различия). +Вы можете использовать те же встроенные типы как generics (с квадратными скобками и типами внутри): -Например, «**Python 3.6+**» означает совместимость с Python 3.6 и выше (включая 3.7, 3.8, 3.9, 3.10 и т.д.). А «**Python 3.9+**» — совместимость с Python 3.9 и выше (включая 3.10 и т.п.). - -Если вы можете использовать **последние версии Python**, используйте примеры для самой новой версии — у них будет **самый лучший и простой синтаксис**, например, «**Python 3.10+**». +* `list` +* `tuple` +* `set` +* `dict` #### List { #list } @@ -167,7 +170,7 @@ John Doe Так как список — это тип, содержащий внутренние типы, укажите их в квадратных скобках: -{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial006_py310.py hl[1] *} /// info | Информация @@ -193,7 +196,7 @@ John Doe Аналогично вы бы объявили `tuple` и `set`: -{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial007_py310.py hl[1] *} Это означает: @@ -208,7 +211,7 @@ John Doe Второй параметр типа — для значений `dict`: -{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial008_py310.py hl[1] *} Это означает: @@ -220,44 +223,20 @@ John Doe Вы можете объявить, что переменная может быть **одним из нескольких типов**, например, `int` или `str`. -В Python 3.6 и выше (включая Python 3.10) вы можете использовать тип `Union` из `typing` и перечислить в квадратных скобках все допустимые типы. +Чтобы это определить, используйте вертикальную черту (`|`) для разделения обоих типов. -В Python 3.10 также появился **новый синтаксис**, где допустимые типы можно указать через вертикальную черту (`|`). - -//// tab | Python 3.10+ +Это называется «объединение» (union), потому что переменная может быть чем угодно из объединения этих двух множеств типов. ```Python hl_lines="1" {!> ../../docs_src/python_types/tutorial008b_py310.py!} ``` -//// - -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial008b_py39.py!} -``` - -//// - -В обоих случаях это означает, что `item` может быть `int` или `str`. +Это означает, что `item` может быть `int` или `str`. #### Возможно `None` { #possibly-none } Вы можете объявить, что значение может иметь определённый тип, например `str`, но также может быть и `None`. -В Python 3.6 и выше (включая Python 3.10) это можно объявить, импортировав и используя `Optional` из модуля `typing`. - -```Python hl_lines="1 4" -{!../../docs_src/python_types/tutorial009_py39.py!} -``` - -Использование `Optional[str]` вместо просто `str` позволит редактору кода помочь вам обнаружить ошибки, когда вы предполагаете, что значение всегда `str`, хотя на самом деле оно может быть и `None`. - -`Optional[Something]` — это на самом деле сокращение для `Union[Something, None]`, они эквивалентны. - -Это также означает, что в Python 3.10 вы можете использовать `Something | None`: - //// tab | Python 3.10+ ```Python hl_lines="1" @@ -266,96 +245,7 @@ John Doe //// -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009_py39.py!} -``` - -//// - -//// tab | Python 3.9+ альтернативный вариант - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009b_py39.py!} -``` - -//// - -#### Использовать `Union` или `Optional` { #using-union-or-optional } - -Если вы используете версию Python ниже 3.10, вот совет с моей весьма **субъективной** точки зрения: - -* 🚨 Избегайте использования `Optional[SomeType]` -* Вместо этого ✨ **используйте `Union[SomeType, None]`** ✨. - -Оба варианта эквивалентны и внутри одинаковы, но я бы рекомендовал `Union` вместо `Optional`, потому что слово «**optional**» («необязательный») может навести на мысль, что значение необязательное, хотя на самом деле оно означает «может быть `None`», даже если параметр не является необязательным и всё ещё обязателен. - -Мне кажется, `Union[SomeType, None]` более явно выражает смысл. - -Речь только о словах и названиях. Но эти слова могут влиять на то, как вы и ваши коллеги думаете о коде. - -В качестве примера возьмём эту функцию: - -{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *} - -Параметр `name` определён как `Optional[str]`, но он **не необязательный** — вы не можете вызвать функцию без этого параметра: - -```Python -say_hi() # О нет, это вызывает ошибку! 😱 -``` - -Параметр `name` всё ещё **обязателен** (не *optional*), потому что у него нет значения по умолчанию. При этом `name` принимает `None` как значение: - -```Python -say_hi(name=None) # Это работает, None допустим 🎉 -``` - -Хорошая новость: как только вы перейдёте на Python 3.10, об этом можно не переживать — вы сможете просто использовать `|` для объединения типов: - -{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *} - -И тогда вам не придётся задумываться о названиях вроде `Optional` и `Union`. 😎 - -#### Generic-типы { #generic-types } - -Типы, которые принимают параметры типов в квадратных скобках, называются **Generic-типами** или **Generics**, например: - -//// tab | Python 3.10+ - -Вы можете использовать те же встроенные типы как generics (с квадратными скобками и типами внутри): - -* `list` -* `tuple` -* `set` -* `dict` - -И, как и в предыдущих версиях Python, из модуля `typing`: - -* `Union` -* `Optional` -* ...и другие. - -В Python 3.10, как альтернативу generics `Union` и `Optional`, можно использовать вертикальную черту (`|`) для объявления объединений типов — это гораздо лучше и проще. - -//// - -//// tab | Python 3.9+ - -Вы можете использовать те же встроенные типы как generics (с квадратными скобками и типами внутри): - -* `list` -* `tuple` -* `set` -* `dict` - -И generics из модуля `typing`: - -* `Union` -* `Optional` -* ...и другие. - -//// +Использование `str | None` вместо просто `str` позволит редактору кода помочь вам обнаружить ошибки, когда вы предполагаете, что значение всегда `str`, хотя на самом деле оно может быть и `None`. ### Классы как типы { #classes-as-types } @@ -363,11 +253,11 @@ say_hi(name=None) # Это работает, None допустим 🎉 Допустим, у вас есть класс `Person` с именем: -{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[1:3] *} Тогда вы можете объявить переменную типа `Person`: -{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[6] *} И снова вы получите полную поддержку редактора кода: @@ -401,21 +291,15 @@ say_hi(name=None) # Это работает, None допустим 🎉 **FastAPI** целиком основан на Pydantic. -Вы увидите намного больше всего этого на практике в [Руководстве пользователя](tutorial/index.md){.internal-link target=_blank}. - -/// tip | Совет - -У Pydantic есть особое поведение, когда вы используете `Optional` или `Union[Something, None]` без значения по умолчанию. Подробнее читайте в документации Pydantic: Required Optional fields. - -/// +Вы увидите намного больше всего этого на практике в [Учебник - Руководство пользователя](tutorial/index.md){.internal-link target=_blank}. ## Подсказки типов с аннотациями метаданных { #type-hints-with-metadata-annotations } -В Python также есть возможность добавлять **дополнительные метаданные** к подсказкам типов с помощью `Annotated`. +В Python также есть возможность добавлять **дополнительные метаданные** к подсказкам типов с помощью `Annotated`. -Начиная с Python 3.9, `Annotated` входит в стандартную библиотеку, поэтому вы можете импортировать его из `typing`. +Вы можете импортировать `Annotated` из `typing`. -{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *} +{* ../../docs_src/python_types/tutorial013_py310.py hl[1,4] *} Сам Python ничего не делает с `Annotated`. А для редакторов кода и других инструментов тип по-прежнему `str`. @@ -453,7 +337,7 @@ say_hi(name=None) # Это работает, None допустим 🎉 * **Документирования** API с использованием OpenAPI: * что затем используется пользовательскими интерфейсами автоматической интерактивной документации. -Всё это может звучать абстрактно. Не волнуйтесь. Вы увидите всё это в действии в [Руководстве пользователя](tutorial/index.md){.internal-link target=_blank}. +Всё это может звучать абстрактно. Не волнуйтесь. Вы увидите всё это в действии в [Учебник - Руководство пользователя](tutorial/index.md){.internal-link target=_blank}. Важно то, что, используя стандартные типы Python в одном месте (вместо добавления дополнительных классов, декораторов и т.д.), **FastAPI** сделает за вас большую часть работы. diff --git a/docs/ru/docs/tutorial/background-tasks.md b/docs/ru/docs/tutorial/background-tasks.md index 8d7b7442f..9fa7a8502 100644 --- a/docs/ru/docs/tutorial/background-tasks.md +++ b/docs/ru/docs/tutorial/background-tasks.md @@ -15,7 +15,7 @@ Сначала импортируйте `BackgroundTasks` и объявите параметр в вашей функции‑обработчике пути с типом `BackgroundTasks`: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[1,13] *} **FastAPI** создаст объект типа `BackgroundTasks` для вас и передаст его через этот параметр. @@ -31,13 +31,13 @@ Так как операция записи не использует `async` и `await`, мы определим функцию как обычную `def`: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[6:9] *} ## Добавление фоновой задачи { #add-the-background-task } Внутри вашей функции‑обработчика пути передайте функцию задачи объекту фоновых задач методом `.add_task()`: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[14] *} `.add_task()` принимает следующие аргументы: @@ -47,7 +47,7 @@ ## Встраивание зависимостей { #dependency-injection } -Использование `BackgroundTasks` также работает с системой встраивания зависимостей, вы можете объявить параметр типа `BackgroundTasks` на нескольких уровнях: в функции‑обработчике пути, в зависимости (dependable), в подзависимости и т. д. +Использование `BackgroundTasks` также работает с системой встраивания зависимостей, вы можете объявить параметр типа `BackgroundTasks` на нескольких уровнях: в функции‑обработчике пути, в зависимости (dependable), в подзависимости и т.д. **FastAPI** знает, что делать в каждом случае и как переиспользовать один и тот же объект, так чтобы все фоновые задачи были объединены и затем выполнены в фоне: @@ -73,7 +73,7 @@ ## Предостережение { #caveat } -Если вам нужно выполнять тяжелые вычисления в фоне, и при этом они не обязательно должны запускаться тем же процессом (например, вам не нужно делиться памятью, переменными и т. п.), вам могут подойти более мощные инструменты, такие как Celery. +Если вам нужно выполнять тяжелые вычисления в фоне, и при этом они не обязательно должны запускаться тем же процессом (например, вам не нужно делиться памятью, переменными и т.п.), вам могут подойти более мощные инструменты, такие как Celery. Они обычно требуют более сложной конфигурации, менеджера очереди сообщений/заданий (например, RabbitMQ или Redis), но позволяют запускать фоновые задачи в нескольких процессах и, что особенно важно, на нескольких серверах. diff --git a/docs/ru/docs/tutorial/bigger-applications.md b/docs/ru/docs/tutorial/bigger-applications.md index 76304523c..3fb36d5a2 100644 --- a/docs/ru/docs/tutorial/bigger-applications.md +++ b/docs/ru/docs/tutorial/bigger-applications.md @@ -85,7 +85,7 @@ from app.routers import items Точно так же, как и в случае с классом `FastAPI`, вам нужно импортировать и создать его «экземпляр»: -{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *} ### *Операции пути* с `APIRouter` { #path-operations-with-apirouter } @@ -93,7 +93,7 @@ from app.routers import items Используйте его так же, как вы использовали бы класс `FastAPI`: -{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} Вы можете думать об `APIRouter` как об «мини-классе `FastAPI`». @@ -117,7 +117,7 @@ from app.routers import items Теперь мы воспользуемся простой зависимостью, чтобы прочитать кастомный HTTP-заголовок `X-Token`: -{* ../../docs_src/bigger_applications/app_an_py39/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} /// tip | Подсказка @@ -149,7 +149,7 @@ from app.routers import items Таким образом, вместо того чтобы добавлять всё это в каждую *операцию пути*, мы можем добавить это в `APIRouter`. -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} Так как путь каждой *операции пути* должен начинаться с `/`, как здесь: @@ -208,7 +208,7 @@ async def read_item(item_id: str): Поэтому мы используем относительный импорт с `..` для зависимостей: -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[3] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[3] title["app/routers/items.py"] *} #### Как работает относительный импорт { #how-relative-imports-work } @@ -279,7 +279,7 @@ from ...dependencies import get_token_header Но мы всё равно можем добавить _ещё_ `tags`, которые будут применяться к конкретной *операции пути*, а также дополнительные `responses`, специфичные для этой *операции пути*: -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[30:31] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[30:31] title["app/routers/items.py"] *} /// tip | Подсказка @@ -305,13 +305,13 @@ from ...dependencies import get_token_header И мы даже можем объявить [глобальные зависимости](dependencies/global-dependencies.md){.internal-link target=_blank}, которые будут объединены с зависимостями для каждого `APIRouter`: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[1,3,7] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *} ### Импорт `APIRouter` { #import-the-apirouter } Теперь мы импортируем другие подмодули, содержащие `APIRouter`: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[4:5] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[4:5] title["app/main.py"] *} Так как файлы `app/routers/users.py` и `app/routers/items.py` являются подмодулями, входящими в один и тот же Python-пакет `app`, мы можем использовать одну точку `.` для импорта через «относительные импорты». @@ -374,13 +374,13 @@ from .routers.users import router Поэтому, чтобы иметь возможность использовать обе в одном файле, мы импортируем подмодули напрямую: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[5] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[5] title["app/main.py"] *} ### Подключение `APIRouter` для `users` и `items` { #include-the-apirouters-for-users-and-items } Теперь давайте подключим `router` из подмодулей `users` и `items`: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[10:11] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[10:11] title["app/main.py"] *} /// info | Примечание @@ -420,13 +420,13 @@ from .routers.users import router Для этого примера всё будет очень просто. Но допустим, что поскольку он используется совместно с другими проектами в организации, мы не можем модифицировать его и добавить `prefix`, `dependencies`, `tags` и т.д. непосредственно в `APIRouter`: -{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} Но мы всё равно хотим задать пользовательский `prefix` при подключении `APIRouter`, чтобы все его *операции пути* начинались с `/admin`, хотим защитить его с помощью `dependencies`, которые у нас уже есть для этого проекта, и хотим включить `tags` и `responses`. Мы можем объявить всё это, не изменяя исходный `APIRouter`, передав эти параметры в `app.include_router()`: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[14:17] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[14:17] title["app/main.py"] *} Таким образом исходный `APIRouter` не будет модифицирован, и мы сможем использовать файл `app/internal/admin.py` сразу в нескольких проектах организации. @@ -447,7 +447,7 @@ from .routers.users import router Здесь мы делаем это... просто чтобы показать, что можем 🤷: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[21:23] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[21:23] title["app/main.py"] *} и это будет работать корректно вместе со всеми другими *операциями пути*, добавленными через `app.include_router()`. diff --git a/docs/ru/docs/tutorial/body-multiple-params.md b/docs/ru/docs/tutorial/body-multiple-params.md index 9d9400494..ddd9c6fdd 100644 --- a/docs/ru/docs/tutorial/body-multiple-params.md +++ b/docs/ru/docs/tutorial/body-multiple-params.md @@ -52,7 +52,7 @@ } ``` -/// note | Внимание +/// note | Заметка Обратите внимание, что хотя параметр `item` был объявлен таким же способом, как и раньше, теперь предполагается, что он находится внутри тела с ключом `item`. @@ -104,12 +104,6 @@ q: str | None = None ``` -Или в Python 3.9: - -```Python -q: Union[str, None] = None -``` - Например: {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} diff --git a/docs/ru/docs/tutorial/body-nested-models.md b/docs/ru/docs/tutorial/body-nested-models.md index 4c914b97f..6610b209c 100644 --- a/docs/ru/docs/tutorial/body-nested-models.md +++ b/docs/ru/docs/tutorial/body-nested-models.md @@ -163,7 +163,7 @@ images: list[Image] например так: -{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *} +{* ../../docs_src/body_nested_models/tutorial008_py310.py hl[13] *} ## Поддержка редактора кода везде { #editor-support-everywhere } @@ -193,7 +193,7 @@ images: list[Image] В этом случае вы принимаете любой `dict`, пока у него есть ключи типа `int` со значениями типа `float`: -{* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *} +{* ../../docs_src/body_nested_models/tutorial009_py310.py hl[7] *} /// tip | Совет diff --git a/docs/ru/docs/tutorial/body.md b/docs/ru/docs/tutorial/body.md index 537d7ebc9..3e55607da 100644 --- a/docs/ru/docs/tutorial/body.md +++ b/docs/ru/docs/tutorial/body.md @@ -72,7 +72,7 @@ * Проведёт валидацию данных. * Если данные некорректны, вернёт понятную и наглядную ошибку, указывающую, где именно и что было некорректно. * Передаст полученные данные в параметр `item`. - * Поскольку внутри функции вы объявили его с типом `Item`, у вас будет поддержка со стороны редактора кода (автозавершение и т. п.) для всех атрибутов и их типов. + * Поскольку внутри функции вы объявили его с типом `Item`, у вас будет поддержка со стороны редактора кода (автозавершение и т.п.) для всех атрибутов и их типов. * Сгенерирует определения JSON Schema для вашей модели; вы можете использовать их и в других местах, если это имеет смысл для вашего проекта. * Эти схемы будут частью сгенерированной схемы OpenAPI и будут использоваться автоматической документацией UIs. @@ -148,14 +148,14 @@ JSON Schema ваших моделей будет частью сгенериро Параметры функции будут распознаны следующим образом: * Если параметр также объявлен в **пути**, он будет использоваться как path-параметр. -* Если параметр имеет **скалярный тип** (например, `int`, `float`, `str`, `bool` и т. п.), он будет интерпретирован как параметр **запроса**. +* Если параметр имеет **скалярный тип** (например, `int`, `float`, `str`, `bool` и т.п.), он будет интерпретирован как параметр **запроса**. * Если параметр объявлен как тип **модели Pydantic**, он будет интерпретирован как **тело** запроса. /// note | Заметка FastAPI понимает, что значение `q` не является обязательным из-за значения по умолчанию `= None`. -Аннотации типов `str | None` (Python 3.10+) или `Union` в `Union[str, None]` (Python 3.9+) не используются FastAPI для определения обязательности; он узнает, что параметр не обязателен, потому что у него есть значение по умолчанию `= None`. +Аннотация типов `str | None` не используется FastAPI для определения обязательности; он узнает, что параметр не обязателен, потому что у него есть значение по умолчанию `= None`. Но добавление аннотаций типов позволит вашему редактору кода лучше вас поддерживать и обнаруживать ошибки. diff --git a/docs/ru/docs/tutorial/cookie-param-models.md b/docs/ru/docs/tutorial/cookie-param-models.md index 182813afd..9b34cf030 100644 --- a/docs/ru/docs/tutorial/cookie-param-models.md +++ b/docs/ru/docs/tutorial/cookie-param-models.md @@ -46,7 +46,7 @@ В некоторых случаях (не особо часто встречающихся) вам может понадобиться **ограничить** cookies, которые вы хотите получать. -Теперь ваш API сам решает, принимать ли cookies. 🤪🍪 +Теперь у вашего API есть возможность контролировать своё согласие на использование cookie. 🤪🍪 Вы можете сконфигурировать Pydantic-модель так, чтобы запретить (`forbid`) любые дополнительные (`extra`) поля: @@ -54,9 +54,9 @@ Если клиент попробует отправить **дополнительные cookies**, то в ответ он получит **ошибку**. -Бедные баннеры cookies, они всеми силами пытаются получить ваше согласие — и всё ради того, чтобы API его отклонил. 🍪 +Бедные баннеры cookies, они всеми силами пытаются получить ваше согласие — и всё ради того, чтобы API его отклонил. 🍪 -Например, если клиент попытается отправить cookie `santa_tracker` со значением `good-list-please`, то в ответ он получит **ошибку**, сообщающую ему, что cookie `santa_tracker` не разрешён: +Например, если клиент попытается отправить cookie `santa_tracker` со значением `good-list-please`, то в ответ он получит **ошибку**, сообщающую ему, что `santa_tracker` cookie не разрешён: ```json { @@ -73,4 +73,4 @@ ## Заключение { #summary } -Вы можете использовать **Pydantic-модели** для объявления **cookies** в **FastAPI**. 😎 +Вы можете использовать **Pydantic-модели** для объявления **cookies** в **FastAPI**. 😎 diff --git a/docs/ru/docs/tutorial/cookie-params.md b/docs/ru/docs/tutorial/cookie-params.md index 2d2eff8d7..8dad3873e 100644 --- a/docs/ru/docs/tutorial/cookie-params.md +++ b/docs/ru/docs/tutorial/cookie-params.md @@ -32,11 +32,11 @@ /// info | Дополнительная информация -Имейте в виду, что, поскольку браузеры обрабатывают cookies особым образом и «за кулисами», они не позволяют JavaScript просто так получать к ним доступ. +Имейте в виду, что, поскольку **браузеры обрабатывают cookies** особым образом и «за кулисами», они **не** позволяют **JavaScript** просто так получать к ним доступ. -Если вы откроете интерфейс документации API на `/docs`, вы сможете увидеть документацию по cookies для ваших операций пути. +Если вы откроете **интерфейс документации API** на `/docs`, вы сможете увидеть **документацию** по cookies для ваших *операции пути*. -Но даже если вы заполните данные и нажмёте «Execute», поскольку UI документации работает с JavaScript, cookies отправлены не будут, и вы увидите сообщение об ошибке, как будто вы не указали никаких значений. +Но даже если вы **заполните данные** и нажмёте «Execute», поскольку UI документации работает с **JavaScript**, cookies отправлены не будут, и вы увидите сообщение об **ошибке**, как будто вы не указали никаких значений. /// diff --git a/docs/ru/docs/tutorial/cors.md b/docs/ru/docs/tutorial/cors.md index d09a31e2c..feaa15968 100644 --- a/docs/ru/docs/tutorial/cors.md +++ b/docs/ru/docs/tutorial/cors.md @@ -46,7 +46,7 @@ * Отдельных HTTP-методов (`POST`, `PUT`) или всех вместе, используя `"*"`. * Отдельных HTTP-заголовков или всех вместе, используя `"*"`. -{* ../../docs_src/cors/tutorial001_py39.py hl[2,6:11,13:19] *} +{* ../../docs_src/cors/tutorial001_py310.py hl[2,6:11,13:19] *} `CORSMiddleware` использует "запрещающие" значения по умолчанию, поэтому вам нужно явным образом разрешить использование отдельных источников, методов или заголовков, чтобы браузеры могли использовать их в кросс-доменном контексте. @@ -77,7 +77,7 @@ ## Больше информации { #more-info } -Для получения более подробной информации о CORS обратитесь к документации CORS от Mozilla. +Для получения более подробной информации о CORS обратитесь к документации CORS от Mozilla. /// note | Технические детали diff --git a/docs/ru/docs/tutorial/debugging.md b/docs/ru/docs/tutorial/debugging.md index 51955835e..483fe8086 100644 --- a/docs/ru/docs/tutorial/debugging.md +++ b/docs/ru/docs/tutorial/debugging.md @@ -6,7 +6,7 @@ В вашем FastAPI приложении, импортируйте и вызовите `uvicorn` напрямую: -{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *} +{* ../../docs_src/debugging/tutorial001_py310.py hl[1,15] *} ### Описание `__name__ == "__main__"` { #about-name-main } @@ -42,7 +42,7 @@ $ python myapp.py то встроенная переменная `__name__`, автоматически создаваемая Python в вашем файле, будет иметь значение строкового типа `"__main__"`. -Тогда выполнится условие и эта часть кода: +Тогда эта часть кода: ```Python uvicorn.run(app, host="0.0.0.0", port=8000) @@ -59,7 +59,7 @@ $ python myapp.py ```Python from myapp import app -# Some more code +# Еще немного кода ``` то автоматическая создаваемая внутри файла `myapp.py` переменная `__name__` будет иметь значение отличающееся от `"__main__"`. @@ -99,7 +99,7 @@ from myapp import app --- -Если используете Pycharm, вы можете выполнить следующие шаги: +Если используете PyCharm, вы можете выполнить следующие шаги: * Открыть "Run" меню. * Выбрать опцию "Debug...". diff --git a/docs/ru/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/ru/docs/tutorial/dependencies/classes-as-dependencies.md index a38e885d4..9a3171e9f 100644 --- a/docs/ru/docs/tutorial/dependencies/classes-as-dependencies.md +++ b/docs/ru/docs/tutorial/dependencies/classes-as-dependencies.md @@ -4,7 +4,7 @@ ## `dict` из предыдущего примера { #a-dict-from-the-previous-example } -В предыдущем примере мы возвращали `dict` из нашей зависимости: +В предыдущем примере мы возвращали `dict` из нашей зависимости («dependable»): {* ../../docs_src/dependencies/tutorial001_an_py310.py hl[9] *} @@ -67,7 +67,7 @@ fluffy = Cat(name="Mr Fluffy") Это относится и к вызываемым объектам без параметров. Работа с ними происходит точно так же, как и для *функций-обработчиков пути* без параметров. -Теперь мы можем изменить зависимость `common_parameters`, указанную выше, на класс `CommonQueryParams`: +Теперь мы можем изменить зависимость («dependable») `common_parameters`, указанную выше, на класс `CommonQueryParams`: {* ../../docs_src/dependencies/tutorial002_an_py310.py hl[11:15] *} @@ -101,7 +101,7 @@ fluffy = Cat(name="Mr Fluffy") Обратите внимание, что в приведенном выше коде мы два раза пишем `CommonQueryParams`: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -109,7 +109,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ без Annotated /// tip | Подсказка @@ -137,7 +137,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams) В этом случае первый `CommonQueryParams`, в: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, ... @@ -145,7 +145,7 @@ commons: Annotated[CommonQueryParams, ... //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ без Annotated /// tip | Подсказка @@ -163,7 +163,7 @@ commons: CommonQueryParams ... На самом деле можно написать просто: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[Any, Depends(CommonQueryParams)] @@ -171,7 +171,7 @@ commons: Annotated[Any, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ без Annotated /// tip | Подсказка @@ -197,7 +197,7 @@ commons = Depends(CommonQueryParams) Но вы видите, что здесь мы имеем некоторое повторение кода, дважды написав `CommonQueryParams`: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -205,7 +205,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ без Annotated /// tip | Подсказка @@ -225,7 +225,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams) Вместо того чтобы писать: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -233,7 +233,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ без Annotated /// tip | Подсказка @@ -249,7 +249,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams) ...следует написать: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends()] @@ -257,7 +257,7 @@ commons: Annotated[CommonQueryParams, Depends()] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ без Annotated /// tip | Подсказка diff --git a/docs/ru/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/ru/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index ef5664448..4cfc4e699 100644 --- a/docs/ru/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/ru/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -14,7 +14,7 @@ Это должен быть `list` состоящий из `Depends()`: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[19] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[19] *} Зависимости из dependencies выполнятся так же, как и обычные зависимости. Но их значения (если они были) не будут переданы в *функцию операции пути*. @@ -30,7 +30,7 @@ /// info | Примечание -В этом примере мы используем выдуманные пользовательские заголовки `X-Key` и `X-Token`. +В этом примере мы используем выдуманные пользовательские HTTP-заголовки `X-Key` и `X-Token`. Но в реальных проектах, при внедрении системы безопасности, вы получите больше пользы используя интегрированные [средства защиты (следующая глава)](../security/index.md){.internal-link target=_blank}. @@ -42,15 +42,15 @@ ### Требования к зависимостям { #dependency-requirements } -Они могут объявлять требования к запросу (например заголовки) или другие подзависимости: +Они могут объявлять требования к запросу (например HTTP-заголовки) или другие подзависимости: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[8,13] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[8,13] *} ### Вызов исключений { #raise-exceptions } Зависимости из dependencies могут вызывать исключения с помощью `raise`, как и обычные зависимости: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[10,15] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[10,15] *} ### Возвращаемые значения { #return-values } @@ -58,7 +58,7 @@ Таким образом, вы можете переиспользовать обычную зависимость (возвращающую значение), которую вы уже используете где-то в другом месте, и хотя значение не будет использоваться, зависимость будет выполнена: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[11,16] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[11,16] *} ## Зависимости для группы *операций путей* { #dependencies-for-a-group-of-path-operations } diff --git a/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md index dc202db61..03a7c083c 100644 --- a/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md @@ -1,6 +1,6 @@ # Зависимости с yield { #dependencies-with-yield } -FastAPI поддерживает зависимости, которые выполняют некоторые дополнительные шаги после завершения. +FastAPI поддерживает зависимости, которые выполняют некоторые дополнительные шаги после завершения. Для этого используйте `yield` вместо `return`, а дополнительные шаги (код) напишите после него. @@ -29,15 +29,15 @@ FastAPI поддерживает зависимости, которые выпо Перед созданием ответа будет выполнен только код до и включая оператор `yield`: -{* ../../docs_src/dependencies/tutorial007_py39.py hl[2:4] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[2:4] *} Значение, полученное из `yield`, внедряется в *операции пути* и другие зависимости: -{* ../../docs_src/dependencies/tutorial007_py39.py hl[4] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[4] *} Код, следующий за оператором `yield`, выполняется после ответа: -{* ../../docs_src/dependencies/tutorial007_py39.py hl[5:6] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[5:6] *} /// tip | Подсказка @@ -57,7 +57,7 @@ FastAPI поддерживает зависимости, которые выпо Точно так же можно использовать `finally`, чтобы убедиться, что обязательные шаги при выходе выполнены независимо от того, было ли исключение или нет. -{* ../../docs_src/dependencies/tutorial007_py39.py hl[3,5] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[3,5] *} ## Подзависимости с `yield` { #sub-dependencies-with-yield } @@ -67,7 +67,7 @@ FastAPI поддерживает зависимости, которые выпо Например, `dependency_c` может зависеть от `dependency_b`, а `dependency_b` — от `dependency_a`: -{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[6,14,22] *} +{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[6,14,22] *} И все они могут использовать `yield`. @@ -75,7 +75,7 @@ FastAPI поддерживает зависимости, которые выпо И, в свою очередь, `dependency_b` нуждается в том, чтобы значение из `dependency_a` (здесь `dep_a`) было доступно для её кода выхода. -{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[18:19,26:27] *} +{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[18:19,26:27] *} Точно так же можно иметь часть зависимостей с `yield`, часть — с `return`, и какие-то из них могут зависеть друг от друга. @@ -109,7 +109,7 @@ FastAPI поддерживает зависимости, которые выпо /// -{* ../../docs_src/dependencies/tutorial008b_an_py39.py hl[18:22,31] *} +{* ../../docs_src/dependencies/tutorial008b_an_py310.py hl[18:22,31] *} Если вы хотите перехватывать исключения и формировать на их основе пользовательский ответ, создайте [Пользовательский обработчик исключений](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}. @@ -117,7 +117,7 @@ FastAPI поддерживает зависимости, которые выпо Если вы ловите исключение с помощью `except` в зависимости с `yield` и не вызываете его снова (или не вызываете новое исключение), FastAPI не сможет заметить, что было исключение — так же, как это происходит в обычном Python: -{* ../../docs_src/dependencies/tutorial008c_an_py39.py hl[15:16] *} +{* ../../docs_src/dependencies/tutorial008c_an_py310.py hl[15:16] *} В этом случае клиент получит *HTTP 500 Internal Server Error*, как и должно быть, поскольку мы не вызываем `HTTPException` или что-то подобное, но на сервере **не будет никаких логов** или других указаний на то, какая была ошибка. 😱 @@ -127,7 +127,7 @@ FastAPI поддерживает зависимости, которые выпо Вы можете повторно вызвать то же самое исключение с помощью `raise`: -{* ../../docs_src/dependencies/tutorial008d_an_py39.py hl[17] *} +{* ../../docs_src/dependencies/tutorial008d_an_py310.py hl[17] *} Теперь клиент получит тот же *HTTP 500 Internal Server Error*, но на сервере в логах будет наше пользовательское `InternalError`. 😎 @@ -190,7 +190,7 @@ participant tasks as Background tasks Но если вы знаете, что не будете использовать зависимость после возврата из *функции-обработчика пути*, вы можете использовать `Depends(scope="function")`, чтобы сообщить FastAPI, что он должен закрыть зависимость после возврата из *функции-обработчика пути*, но **до того**, как **ответ будет отправлен**. -{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *} +{* ../../docs_src/dependencies/tutorial008e_an_py310.py hl[12,16] *} `Depends()` принимает параметр `scope`, который может быть: @@ -269,7 +269,7 @@ with open("./somefile.txt") as f: Их также можно использовать внутри зависимостей **FastAPI** с `yield`, применяя операторы `with` или `async with` внутри функции зависимости: -{* ../../docs_src/dependencies/tutorial010_py39.py hl[1:9,13] *} +{* ../../docs_src/dependencies/tutorial010_py310.py hl[1:9,13] *} /// tip | Подсказка diff --git a/docs/ru/docs/tutorial/dependencies/global-dependencies.md b/docs/ru/docs/tutorial/dependencies/global-dependencies.md index 2347c6dd8..f488322a9 100644 --- a/docs/ru/docs/tutorial/dependencies/global-dependencies.md +++ b/docs/ru/docs/tutorial/dependencies/global-dependencies.md @@ -6,10 +6,10 @@ В этом случае они будут применяться ко всем *операциям пути* в приложении: -{* ../../docs_src/dependencies/tutorial012_an_py39.py hl[17] *} +{* ../../docs_src/dependencies/tutorial012_an_py310.py hl[17] *} Все способы [добавления `dependencies` (зависимостей) в *декораторах операций пути*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} по-прежнему применимы, но в данном случае зависимости применяются ко всем *операциям пути* приложения. ## Зависимости для групп *операций пути* { #dependencies-for-groups-of-path-operations } -Позднее, читая о том, как структурировать более крупные [приложения, содержащие много файлов](../../tutorial/bigger-applications.md){.internal-link target=_blank}, вы узнаете, как объявить один параметр `dependencies` для целой группы *операций пути*. +Позднее, читая о том, как структурировать более крупные приложения ([приложения, содержащие много файлов](../../tutorial/bigger-applications.md){.internal-link target=_blank}), возможно, состоящие из нескольких файлов, вы узнаете, как объявить один параметр `dependencies` для целой группы *операций пути*. diff --git a/docs/ru/docs/tutorial/dependencies/index.md b/docs/ru/docs/tutorial/dependencies/index.md index 98b0d59c6..29f735ab6 100644 --- a/docs/ru/docs/tutorial/dependencies/index.md +++ b/docs/ru/docs/tutorial/dependencies/index.md @@ -1,6 +1,6 @@ # Зависимости { #dependencies } -**FastAPI** имеет очень мощную, но интуитивную систему **Инъекция зависимостей**. +**FastAPI** имеет очень мощную, но интуитивную систему **Инъекция зависимостей**. Она спроектирована так, чтобы быть очень простой в использовании и облегчать любому разработчику интеграцию других компонентов с **FastAPI**. diff --git a/docs/ru/docs/tutorial/dependencies/sub-dependencies.md b/docs/ru/docs/tutorial/dependencies/sub-dependencies.md index da31a6682..3c71defd8 100644 --- a/docs/ru/docs/tutorial/dependencies/sub-dependencies.md +++ b/docs/ru/docs/tutorial/dependencies/sub-dependencies.md @@ -58,11 +58,11 @@ query_extractor --> query_or_cookie_extractor --> read_query Если одна из ваших зависимостей объявлена несколько раз для одной и той же *функции операции пути*, например, несколько зависимостей имеют общую подзависимость, **FastAPI** будет знать, что вызывать эту подзависимость нужно только один раз за запрос. -При этом возвращаемое значение будет сохранено в "кэш" и будет передано всем "зависимым" функциям, которые нуждаются в нем внутри этого конкретного запроса, вместо того, чтобы вызывать зависимость несколько раз для одного и того же запроса. +При этом возвращаемое значение будет сохранено в «кэш» и будет передано всем "зависимым" функциям, которые нуждаются в нем внутри этого конкретного запроса, вместо того, чтобы вызывать зависимость несколько раз для одного и того же запроса. В расширенном сценарии, когда вы знаете, что вам нужно, чтобы зависимость вызывалась на каждом шаге (возможно, несколько раз) в одном и том же запросе, вместо использования "кэшированного" значения, вы можете установить параметр `use_cache=False` при использовании `Depends`: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python hl_lines="1" async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]): @@ -71,7 +71,7 @@ async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_ca //// -//// tab | Python 3.9+ без Annotated +//// tab | Python 3.10+ без Annotated /// tip | Подсказка diff --git a/docs/ru/docs/tutorial/encoder.md b/docs/ru/docs/tutorial/encoder.md index 16981f79d..28e2a49c0 100644 --- a/docs/ru/docs/tutorial/encoder.md +++ b/docs/ru/docs/tutorial/encoder.md @@ -10,9 +10,9 @@ Представим, что у вас есть база данных `fake_db`, которая принимает только JSON-совместимые данные. -Например, он не принимает объекты `datetime`, так как они не совместимы с JSON. +Например, она не принимает объекты `datetime`, так как они не совместимы с JSON. -В таком случае объект `datetime` следует преобразовать в строку соответствующую формату ISO. +В таком случае объект `datetime` следует преобразовать в строку, соответствующую формату ISO. Точно так же эта база данных не может принять Pydantic-модель (объект с атрибутами), а только `dict`. diff --git a/docs/ru/docs/tutorial/extra-models.md b/docs/ru/docs/tutorial/extra-models.md index 03156f2b4..f9b63ca70 100644 --- a/docs/ru/docs/tutorial/extra-models.md +++ b/docs/ru/docs/tutorial/extra-models.md @@ -190,9 +190,9 @@ some_variable: PlaneItem | CarItem Таким же образом вы можете объявлять HTTP-ответы, возвращающие списки объектов. -Для этого используйте стандартный `typing.List` в Python (или просто `list` в Python 3.9 и выше): +Для этого используйте стандартный `list` в Python: -{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *} +{* ../../docs_src/extra_models/tutorial004_py310.py hl[18] *} ## Ответ с произвольным `dict` { #response-with-arbitrary-dict } @@ -200,9 +200,9 @@ some_variable: PlaneItem | CarItem Это полезно, если вы заранее не знаете корректных названий полей/атрибутов (которые будут нужны при использовании Pydantic-модели). -В этом случае вы можете использовать `typing.Dict` (или просто `dict` в Python 3.9 и выше): +В этом случае вы можете использовать `dict`: -{* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *} +{* ../../docs_src/extra_models/tutorial005_py310.py hl[6] *} ## Резюме { #recap } diff --git a/docs/ru/docs/tutorial/first-steps.md b/docs/ru/docs/tutorial/first-steps.md index 798c03d51..cee264ff4 100644 --- a/docs/ru/docs/tutorial/first-steps.md +++ b/docs/ru/docs/tutorial/first-steps.md @@ -2,7 +2,7 @@ Самый простой файл FastAPI может выглядеть так: -{* ../../docs_src/first_steps/tutorial001_py39.py *} +{* ../../docs_src/first_steps/tutorial001_py310.py *} Скопируйте это в файл `main.py`. @@ -183,7 +183,7 @@ Deploying to FastAPI Cloud... ### Шаг 1: импортируйте `FastAPI` { #step-1-import-fastapi } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[1] *} `FastAPI` — это класс на Python, который предоставляет всю функциональность для вашего API. @@ -197,7 +197,7 @@ Deploying to FastAPI Cloud... ### Шаг 2: создайте экземпляр `FastAPI` { #step-2-create-a-fastapi-instance } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[3] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[3] *} Здесь переменная `app` будет экземпляром класса `FastAPI`. @@ -266,12 +266,12 @@ https://example.com/items/foo #### Определите *декоратор операции пути (path operation decorator)* { #define-a-path-operation-decorator } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[6] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[6] *} `@app.get("/")` сообщает **FastAPI**, что функция прямо под ним отвечает за обработку запросов, поступающих: * по пути `/` -* с использованием get операции +* с использованием get операции /// info | Информация о `@decorator` @@ -320,7 +320,7 @@ https://example.com/items/foo * **операция**: `get`. * **функция**: функция ниже «декоратора» (ниже `@app.get("/")`). -{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[7] *} Это функция на Python. @@ -332,7 +332,7 @@ https://example.com/items/foo Вы также можете определить её как обычную функцию вместо `async def`: -{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *} +{* ../../docs_src/first_steps/tutorial003_py310.py hl[7] *} /// note | Примечание @@ -342,7 +342,7 @@ https://example.com/items/foo ### Шаг 5: верните содержимое { #step-5-return-the-content } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[8] *} Вы можете вернуть `dict`, `list`, отдельные значения `str`, `int` и т.д. diff --git a/docs/ru/docs/tutorial/handling-errors.md b/docs/ru/docs/tutorial/handling-errors.md index 2e00d7075..fbd82cf28 100644 --- a/docs/ru/docs/tutorial/handling-errors.md +++ b/docs/ru/docs/tutorial/handling-errors.md @@ -11,7 +11,7 @@ * Элемент, к которому клиент пытался получить доступ, не существует. * и т.д. -В таких случаях обычно возвращается **HTTP-код статуса ответа** в диапазоне **400** (от 400 до 499). +В таких случаях обычно возвращают **HTTP статус-код** в диапазоне **400** (от 400 до 499). Они похожи на двухсотые HTTP статус-коды (от 200 до 299), которые означают, что запрос обработан успешно. @@ -25,7 +25,7 @@ ### Импортируйте `HTTPException` { #import-httpexception } -{* ../../docs_src/handling_errors/tutorial001_py39.py hl[1] *} +{* ../../docs_src/handling_errors/tutorial001_py310.py hl[1] *} ### Вызовите `HTTPException` в своем коде { #raise-an-httpexception-in-your-code } @@ -39,7 +39,7 @@ В данном примере, когда клиент запрашивает элемент по несуществующему ID, возникает исключение со статус-кодом `404`: -{* ../../docs_src/handling_errors/tutorial001_py39.py hl[11] *} +{* ../../docs_src/handling_errors/tutorial001_py310.py hl[11] *} ### Возвращаемый ответ { #the-resulting-response } @@ -71,13 +71,13 @@ ## Добавление пользовательских заголовков { #add-custom-headers } -В некоторых ситуациях полезно иметь возможность добавлять пользовательские заголовки к ошибке HTTP. Например, для некоторых типов безопасности. +В некоторых ситуациях полезно иметь возможность добавлять пользовательские HTTP-заголовки к ошибке HTTP. Например, для некоторых типов безопасности. Скорее всего, вам не потребуется использовать его непосредственно в коде. Но в случае, если это необходимо для продвинутого сценария, можно добавить пользовательские заголовки: -{* ../../docs_src/handling_errors/tutorial002_py39.py hl[14] *} +{* ../../docs_src/handling_errors/tutorial002_py310.py hl[14] *} ## Установка пользовательских обработчиков исключений { #install-custom-exception-handlers } @@ -89,7 +89,7 @@ Можно добавить собственный обработчик исключений с помощью `@app.exception_handler()`: -{* ../../docs_src/handling_errors/tutorial003_py39.py hl[5:7,13:18,24] *} +{* ../../docs_src/handling_errors/tutorial003_py310.py hl[5:7,13:18,24] *} Здесь, если запросить `/unicorns/yolo`, то *операция пути* вызовет `UnicornException`. @@ -127,7 +127,7 @@ Обработчик исключения получит объект `Request` и исключение. -{* ../../docs_src/handling_errors/tutorial004_py39.py hl[2,14:19] *} +{* ../../docs_src/handling_errors/tutorial004_py310.py hl[2,14:19] *} Теперь, если перейти к `/items/foo`, то вместо стандартной JSON-ошибки с: @@ -159,7 +159,7 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa Например, для этих ошибок можно вернуть обычный текстовый ответ вместо JSON: -{* ../../docs_src/handling_errors/tutorial004_py39.py hl[3:4,9:11,25] *} +{* ../../docs_src/handling_errors/tutorial004_py310.py hl[3:4,9:11,25] *} /// note | Технические детали @@ -183,7 +183,7 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa Вы можете использовать его при разработке приложения для регистрации тела и его отладки, возврата пользователю и т.д. -{* ../../docs_src/handling_errors/tutorial005_py39.py hl[14] *} +{* ../../docs_src/handling_errors/tutorial005_py310.py hl[14] *} Теперь попробуйте отправить недействительный элемент, например: @@ -239,6 +239,6 @@ from starlette.exceptions import HTTPException as StarletteHTTPException Если вы хотите использовать исключение вместе с теми же обработчиками исключений по умолчанию из **FastAPI**, вы можете импортировать и повторно использовать обработчики исключений по умолчанию из `fastapi.exception_handlers`: -{* ../../docs_src/handling_errors/tutorial006_py39.py hl[2:5,15,21] *} +{* ../../docs_src/handling_errors/tutorial006_py310.py hl[2:5,15,21] *} В этом примере вы просто `выводите в терминал` ошибку с очень выразительным сообщением, но идея вам понятна. Вы можете использовать исключение, а затем просто повторно использовать стандартные обработчики исключений. diff --git a/docs/ru/docs/tutorial/metadata.md b/docs/ru/docs/tutorial/metadata.md index e4fe5fb54..221655aa5 100644 --- a/docs/ru/docs/tutorial/metadata.md +++ b/docs/ru/docs/tutorial/metadata.md @@ -18,7 +18,7 @@ Вы можете задать их следующим образом: -{* ../../docs_src/metadata/tutorial001_py39.py hl[3:16, 19:32] *} +{* ../../docs_src/metadata/tutorial001_py310.py hl[3:16, 19:32] *} /// tip | Подсказка @@ -36,7 +36,7 @@ К примеру: -{* ../../docs_src/metadata/tutorial001_1_py39.py hl[31] *} +{* ../../docs_src/metadata/tutorial001_1_py310.py hl[31] *} ## Метаданные для тегов { #metadata-for-tags } @@ -58,7 +58,7 @@ Создайте метаданные для ваших тегов и передайте их в параметре `openapi_tags`: -{* ../../docs_src/metadata/tutorial004_py39.py hl[3:16,18] *} +{* ../../docs_src/metadata/tutorial004_py310.py hl[3:16,18] *} Помните, что вы можете использовать Markdown внутри описания, к примеру "login" будет отображен жирным шрифтом (**login**) и "fancy" будет отображаться курсивом (_fancy_). @@ -72,7 +72,7 @@ Используйте параметр `tags` с вашими *операциями пути* (и `APIRouter`ами), чтобы присвоить им различные теги: -{* ../../docs_src/metadata/tutorial004_py39.py hl[21,26] *} +{* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} /// info | Дополнительная информация @@ -100,7 +100,7 @@ К примеру, чтобы задать её отображение по адресу `/api/v1/openapi.json`: -{* ../../docs_src/metadata/tutorial002_py39.py hl[3] *} +{* ../../docs_src/metadata/tutorial002_py310.py hl[3] *} Если вы хотите отключить схему OpenAPI полностью, вы можете задать `openapi_url=None`, это также отключит пользовательские интерфейсы документации, которые её используют. @@ -117,4 +117,4 @@ К примеру, чтобы задать отображение Swagger UI по адресу `/documentation` и отключить ReDoc: -{* ../../docs_src/metadata/tutorial003_py39.py hl[3] *} +{* ../../docs_src/metadata/tutorial003_py310.py hl[3] *} diff --git a/docs/ru/docs/tutorial/middleware.md b/docs/ru/docs/tutorial/middleware.md index a83d3c011..734545cd8 100644 --- a/docs/ru/docs/tutorial/middleware.md +++ b/docs/ru/docs/tutorial/middleware.md @@ -1,10 +1,8 @@ # Middleware (Промежуточный слой) { #middleware } -Вы можете добавить промежуточный слой (middleware) в **FastAPI** приложение. - -"Middleware" это функция, которая выполняется с каждым запросом до его обработки какой-либо конкретной *операцией пути*. -А также с каждым ответом перед его возвращением. +Вы можете добавить middleware (промежуточный слой) в **FastAPI** приложение. +"Middleware" - это функция, которая выполняется с каждым **запросом** до его обработки какой-либо конкретной *операцией пути*. А также с каждым **ответом** перед его возвращением. * Она принимает каждый поступающий **запрос**. * Может что-то сделать с этим **запросом** или выполнить любой нужный код. @@ -23,23 +21,23 @@ ## Создание middleware { #create-a-middleware } -Для создания middleware используйте декоратор `@app.middleware("http")`. +Для создания middleware используйте декоратор `@app.middleware("http")` поверх функции. Функция middleware получает: -* `request` (объект запроса). +* `request`. * Функцию `call_next`, которая получает `request` в качестве параметра. * Эта функция передаёт `request` соответствующей *операции пути*. - * Затем она возвращает ответ `response`, сгенерированный *операцией пути*. -* Также имеется возможность видоизменить `response`, перед тем как его вернуть. + * Затем она возвращает `response`, сгенерированный соответствующей *операцией пути*. +* Также имеется возможность видоизменить `response` перед тем как его вернуть. -{* ../../docs_src/middleware/tutorial001_py39.py hl[8:9,11,14] *} +{* ../../docs_src/middleware/tutorial001_py310.py hl[8:9,11,14] *} -/// tip | Примечание +/// tip | Совет -Имейте в виду, что можно добавлять свои собственные заголовки при помощи префикса 'X-'. +Имейте в виду, что можно добавлять проприетарные HTTP-заголовки с префиксом `X-`. -Если же вы хотите добавить собственные заголовки, которые клиент сможет увидеть в браузере, то вам потребуется добавить их в настройки CORS ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}), используя параметр `expose_headers`, см. документацию Starlette's CORS docs. +Но если вы хотите, чтобы клиент в браузере мог видеть ваши пользовательские заголовки, необходимо добавить их в настройки CORS ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}), используя параметр `expose_headers`, описанный в документации по CORS Starlette. /// @@ -53,17 +51,17 @@ ### До и после `response` { #before-and-after-the-response } -Вы можете добавить код, использующий `request` до передачи его какой-либо *операции пути*. +Вы можете добавить код, использующий `request`, до передачи его какой-либо *операции пути*. А также после формирования `response`, до того, как вы его вернёте. Например, вы можете добавить собственный заголовок `X-Process-Time`, содержащий время в секундах, необходимое для обработки запроса и генерации ответа: -{* ../../docs_src/middleware/tutorial001_py39.py hl[10,12:13] *} +{* ../../docs_src/middleware/tutorial001_py310.py hl[10,12:13] *} -/// tip | Примечание +/// tip | Совет -Мы используем `time.perf_counter()` вместо `time.time()` для обеспечения большей точности наших примеров. 🤓 +Мы используем `time.perf_counter()` вместо `time.time()` для обеспечения большей точности в таких случаях. 🤓 /// @@ -94,4 +92,4 @@ app.add_middleware(MiddlewareB) О других middleware вы можете узнать больше в разделе [Advanced User Guide: Advanced Middleware](../advanced/middleware.md){.internal-link target=_blank}. -В следующем разделе вы можете прочитать, как настроить CORS с помощью middleware. +В следующем разделе вы можете прочитать, как настроить CORS с помощью middleware. diff --git a/docs/ru/docs/tutorial/path-operation-configuration.md b/docs/ru/docs/tutorial/path-operation-configuration.md index 112a1efca..31531c67f 100644 --- a/docs/ru/docs/tutorial/path-operation-configuration.md +++ b/docs/ru/docs/tutorial/path-operation-configuration.md @@ -4,7 +4,7 @@ /// warning | Внимание -Помните, что эти параметры передаются непосредственно *декоратору операций пути*, а не вашей *функции-обработчику операций пути*. +Помните, что эти параметры передаются непосредственно *декоратору операций пути*, а не вашей *функции-обработчику пути*. /// @@ -46,7 +46,7 @@ **FastAPI** поддерживает это так же, как и в случае с обычными строками: -{* ../../docs_src/path_operation_configuration/tutorial002b_py39.py hl[1,8:10,13,18] *} +{* ../../docs_src/path_operation_configuration/tutorial002b_py310.py hl[1,8:10,13,18] *} ## Краткое и развёрнутое содержание { #summary-and-description } @@ -56,7 +56,7 @@ ## Описание из строк документации { #description-from-docstring } -Так как описания обычно длинные и содержат много строк, вы можете объявить описание *операции пути* в функции строки документации и **FastAPI** прочитает её отсюда. +Так как описания обычно длинные и содержат много строк, вы можете объявить описание *операции пути* в строке документации функции, и **FastAPI** прочитает её оттуда. Вы можете использовать Markdown в строке документации, и он будет интерпретирован и отображён корректно (с учетом отступа в строке документации). @@ -90,9 +90,9 @@ OpenAPI указывает, что каждой *операции пути* не ## Обозначение *операции пути* как устаревшей { #deprecate-a-path-operation } -Если вам необходимо пометить *операцию пути* как устаревшую, при этом не удаляя её, передайте параметр `deprecated`: +Если вам необходимо пометить *операцию пути* как устаревшую, при этом не удаляя её, передайте параметр `deprecated`: -{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *} +{* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *} Он будет четко помечен как устаревший в интерактивной документации: diff --git a/docs/ru/docs/tutorial/path-params-numeric-validations.md b/docs/ru/docs/tutorial/path-params-numeric-validations.md index f0fe78805..6c1148b60 100644 --- a/docs/ru/docs/tutorial/path-params-numeric-validations.md +++ b/docs/ru/docs/tutorial/path-params-numeric-validations.md @@ -44,7 +44,7 @@ Path-параметр всегда является обязательным, п И если вам больше ничего не нужно указывать для этого параметра, то нет необходимости использовать `Query`. -Но вам по-прежнему нужно использовать `Path` для path-параметра `item_id`. И если по какой-либо причине вы не хотите использовать `Annotated`, то могут возникнуть небольшие сложности. +Но вам по-прежнему нужно использовать `Path` для path-параметра `item_id`. И по какой-либо причине вы не хотите использовать `Annotated`. Если вы поместите параметр со значением по умолчанию перед другим параметром, у которого нет значения по умолчанию, то Python укажет на ошибку. @@ -54,11 +54,11 @@ Path-параметр всегда является обязательным, п Поэтому вы можете определить функцию так: -{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_py310.py hl[7] *} Но имейте в виду, что если вы используете `Annotated`, вы не столкнётесь с этой проблемой, так как вы не используете значения по умолчанию параметров функции для `Query()` или `Path()`. -{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py310.py *} ## Задайте нужный вам порядок параметров, полезные приёмы { #order-the-parameters-as-you-need-tricks } @@ -83,13 +83,13 @@ Path-параметр всегда является обязательным, п Python не будет ничего делать с `*`, но он будет знать, что все следующие параметры являются именованными аргументами (парами ключ-значение), также известными как kwargs, даже если у них нет значений по умолчанию. -{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_py310.py hl[7] *} ### Лучше с `Annotated` { #better-with-annotated } Имейте в виду, что если вы используете `Annotated`, то, поскольку вы не используете значений по умолчанию для параметров функции, у вас не возникнет подобной проблемы и вам, вероятно, не придётся использовать `*`. -{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py310.py hl[10] *} ## Валидация числовых данных: больше или равно { #number-validations-greater-than-or-equal } @@ -97,7 +97,7 @@ Python не будет ничего делать с `*`, но он будет з В этом примере при указании `ge=1`, параметр `item_id` должен быть целым числом "`g`reater than or `e`qual" — больше или равно `1`. -{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py310.py hl[10] *} ## Валидация числовых данных: больше и меньше или равно { #number-validations-greater-than-and-less-than-or-equal } @@ -106,7 +106,7 @@ Python не будет ничего делать с `*`, но он будет з * `gt`: больше (`g`reater `t`han) * `le`: меньше или равно (`l`ess than or `e`qual) -{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py310.py hl[10] *} ## Валидация числовых данных: числа с плавающей точкой, больше и меньше { #number-validations-floats-greater-than-and-less-than } @@ -118,7 +118,7 @@ Python не будет ничего делать с `*`, но он будет з То же самое справедливо и для lt. -{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *} +{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py310.py hl[13] *} ## Резюме { #recap } diff --git a/docs/ru/docs/tutorial/path-params.md b/docs/ru/docs/tutorial/path-params.md index 83a7ed3ff..729569748 100644 --- a/docs/ru/docs/tutorial/path-params.md +++ b/docs/ru/docs/tutorial/path-params.md @@ -2,7 +2,7 @@ Вы можете определить "параметры" или "переменные" пути, используя синтаксис форматированных строк Python: -{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *} +{* ../../docs_src/path_params/tutorial001_py310.py hl[6:7] *} Значение параметра пути `item_id` будет передано в функцию в качестве аргумента `item_id`. @@ -16,7 +16,7 @@ Вы можете объявить тип параметра пути в функции, используя стандартные аннотации типов Python: -{* ../../docs_src/path_params/tutorial002_py39.py hl[7] *} +{* ../../docs_src/path_params/tutorial002_py310.py hl[7] *} Здесь, `item_id` объявлен типом `int`. @@ -26,7 +26,7 @@ /// -## Преобразование данных { #data-conversion } +## Преобразование данных { #data-conversion } Если запустите этот пример и перейдёте по адресу: http://127.0.0.1:8000/items/3, то увидите ответ: @@ -38,7 +38,7 @@ Обратите внимание на значение `3`, которое получила (и вернула) функция. Это целочисленный Python `int`, а не строка `"3"`. -Используя такое объявление типов, **FastAPI** выполняет автоматический "парсинг" запросов. +Используя такое объявление типов, **FastAPI** выполняет автоматический HTTP-запрос "парсинг". /// @@ -118,13 +118,13 @@ Поскольку *операции пути* выполняются в порядке их объявления, необходимо, чтобы путь для `/users/me` был объявлен раньше, чем путь для `/users/{user_id}`: -{* ../../docs_src/path_params/tutorial003_py39.py hl[6,11] *} +{* ../../docs_src/path_params/tutorial003_py310.py hl[6,11] *} Иначе путь для `/users/{user_id}` также будет соответствовать `/users/me`, "подразумевая", что он получает параметр `user_id` со значением `"me"`. Аналогично, вы не можете переопределить операцию с путем: -{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *} +{* ../../docs_src/path_params/tutorial003b_py310.py hl[6,11] *} Первый будет выполняться всегда, так как путь совпадает первым. @@ -140,11 +140,11 @@ Затем создайте атрибуты класса с фиксированными допустимыми значениями: -{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[1,6:9] *} /// tip | Подсказка -Если интересно, то "AlexNet", "ResNet" и "LeNet" - это названия моделей Машинного обучения. +Если интересно, то "AlexNet", "ResNet" и "LeNet" - это названия моделей Машинного обучения. /// @@ -152,7 +152,7 @@ Определите *параметр пути*, используя в аннотации типа класс перечисления (`ModelName`), созданный ранее: -{* ../../docs_src/path_params/tutorial005_py39.py hl[16] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[16] *} ### Проверьте документацию { #check-the-docs } @@ -168,13 +168,13 @@ Вы можете сравнить это значение с *элементом перечисления* класса `ModelName`: -{* ../../docs_src/path_params/tutorial005_py39.py hl[17] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[17] *} #### Получение *значения перечисления* { #get-the-enumeration-value } Можно получить фактическое значение (в данном случае - `str`) с помощью `model_name.value` или в общем случае `your_enum_member.value`: -{* ../../docs_src/path_params/tutorial005_py39.py hl[20] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[20] *} /// tip | Подсказка @@ -188,8 +188,8 @@ Они будут преобразованы в соответствующие значения (в данном случае - строки) перед их возвратом клиенту: -{* ../../docs_src/path_params/tutorial005_py39.py hl[18,21,23] *} -Вы отправите клиенту такой JSON-ответ: +{* ../../docs_src/path_params/tutorial005_py310.py hl[18,21,23] *} +На стороне клиента вы получите такой JSON-ответ: ```JSON { @@ -226,7 +226,7 @@ OpenAPI не поддерживает способов объявления *п Можете использовать так: -{* ../../docs_src/path_params/tutorial004_py39.py hl[6] *} +{* ../../docs_src/path_params/tutorial004_py310.py hl[6] *} /// tip | Подсказка @@ -241,7 +241,7 @@ OpenAPI не поддерживает способов объявления *п Используя **FastAPI** вместе со стандартными объявлениями типов Python (короткими и интуитивно понятными), вы получаете: * Поддержку редактора кода (проверку ошибок, автозавершение и т.п.) -* "Парсинг" данных +* "Парсинг" данных * Валидацию данных * Аннотации API и автоматическую документацию diff --git a/docs/ru/docs/tutorial/query-param-models.md b/docs/ru/docs/tutorial/query-param-models.md index 5ad7f1d99..7f29740ac 100644 --- a/docs/ru/docs/tutorial/query-param-models.md +++ b/docs/ru/docs/tutorial/query-param-models.md @@ -6,7 +6,7 @@ /// note | Заметка -Этот функционал доступен с версии `0.115.0`. 🤓 +Это поддерживается начиная с версии FastAPI `0.115.0`. 🤓 /// diff --git a/docs/ru/docs/tutorial/query-params-str-validations.md b/docs/ru/docs/tutorial/query-params-str-validations.md index 2bc2fb22c..43cbcad03 100644 --- a/docs/ru/docs/tutorial/query-params-str-validations.md +++ b/docs/ru/docs/tutorial/query-params-str-validations.md @@ -47,40 +47,16 @@ FastAPI поймёт, что значение `q` не обязательно, У нас была такая аннотация типа: -//// tab | Python 3.10+ - ```Python q: str | None = None ``` -//// - -//// tab | Python 3.9+ - -```Python -q: Union[str, None] = None -``` - -//// - Мы «обернём» это в `Annotated`, и получится: -//// tab | Python 3.10+ - ```Python q: Annotated[str | None] = None ``` -//// - -//// tab | Python 3.9+ - -```Python -q: Annotated[Union[str, None]] = None -``` - -//// - Обе версии означают одно и то же: `q` — параметр, который может быть `str` или `None`, и по умолчанию равен `None`. А теперь к самому интересному. 🎉 @@ -109,7 +85,7 @@ q: Annotated[Union[str, None]] = None ## Альтернатива (устаревшее): `Query` как значение по умолчанию { #alternative-old-query-as-the-default-value } -В предыдущих версиях FastAPI (до 0.95.0) требовалось использовать `Query` как значение по умолчанию для параметра вместо помещения его в `Annotated`. Скорее всего вы ещё встретите такой код, поэтому поясню. +В предыдущих версиях FastAPI (до 0.95.0) требовалось использовать `Query` как значение по умолчанию для параметра вместо помещения его в `Annotated`. Скорее всего вы ещё встретите такой код, поэтому поясню. /// tip | Подсказка @@ -191,7 +167,7 @@ q: str = Query(default="rick") ## Регулярные выражения { #add-regular-expressions } -Вы можете определить регулярное выражение `pattern`, которому должен соответствовать параметр: +Вы можете определить регулярное выражение `pattern`, которому должен соответствовать параметр: {* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} @@ -211,7 +187,7 @@ q: str = Query(default="rick") Допустим, вы хотите объявить, что query-параметр `q` должен иметь `min_length` равный `3` и значение по умолчанию `"fixedquery"`: -{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial005_an_py310.py hl[9] *} /// note | Примечание @@ -241,7 +217,7 @@ q: Annotated[str | None, Query(min_length=3)] = None Поэтому, когда вам нужно объявить значение как обязательное при использовании `Query`, просто не указывайте значение по умолчанию: -{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial006_an_py310.py hl[9] *} ### Обязательный, но может быть `None` { #required-can-be-none } @@ -292,7 +268,7 @@ http://localhost:8000/items/?q=foo&q=bar Можно также определить значение по умолчанию как `list`, если ничего не передано: -{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial012_an_py310.py hl[9] *} Если вы перейдёте по адресу: @@ -315,7 +291,7 @@ http://localhost:8000/items/ Можно использовать `list` напрямую вместо `list[str]`: -{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial013_an_py310.py hl[9] *} /// note | Примечание @@ -371,7 +347,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems Предположим, этот параметр вам больше не нравится. -Его нужно оставить на какое‑то время, так как клиенты его используют, но вы хотите, чтобы в документации он явно отображался как устаревший. +Его нужно оставить на какое‑то время, так как клиенты его используют, но вы хотите, чтобы в документации он явно отображался как устаревший. Тогда передайте параметр `deprecated=True` в `Query`: @@ -401,7 +377,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems /// -Например, эта кастомная проверка убеждается, что ID элемента начинается с `isbn-` для номера книги ISBN или с `imdb-` для ID URL фильма на IMDB: +Например, эта кастомная проверка убеждается, что ID элемента начинается с `isbn-` для номера книги ISBN или с `imdb-` для ID URL фильма на IMDB: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} @@ -435,7 +411,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems #### Случайный элемент { #a-random-item } -С помощью `data.items()` мы получаем итерируемый объект с кортежами, содержащими ключ и значение для каждого элемента словаря. +С помощью `data.items()` мы получаем итерируемый объект с кортежами, содержащими ключ и значение для каждого элемента словаря. Мы превращаем этот итерируемый объект в обычный `list` через `list(data.items())`. diff --git a/docs/ru/docs/tutorial/query-params.md b/docs/ru/docs/tutorial/query-params.md index be1c0e46e..cbacb129c 100644 --- a/docs/ru/docs/tutorial/query-params.md +++ b/docs/ru/docs/tutorial/query-params.md @@ -2,7 +2,7 @@ Когда вы объявляете параметры функции, которые не являются параметрами пути, они автоматически интерпретируются как "query"-параметры. -{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *} +{* ../../docs_src/query_params/tutorial001_py310.py hl[9] *} Query-параметры представляют из себя набор пар ключ-значение, которые идут после знака `?` в URL-адресе, разделенные символами `&`. @@ -24,7 +24,7 @@ http://127.0.0.1:8000/items/?skip=0&limit=10 Все те же правила, которые применяются к path-параметрам, также применяются и query-параметрам: * Поддержка от редактора кода (очевидно) -* "Парсинг" данных +* "Парсинг" данных * Проверка на соответствие данных (Валидация) * Автоматическая документация @@ -121,13 +121,13 @@ http://127.0.0.1:8000/items/foo?short=yes ## Обязательные query-параметры { #required-query-parameters } -Когда вы объявляете значение по умолчанию для параметра, который не является path-параметром (в этом разделе, мы пока что познакомились только с path-параметрами), то он не является обязательным. +Когда вы объявляете значение по умолчанию для параметра, который не является path-параметром (в этом разделе мы пока что рассмотрели только query-параметры), то он не является обязательным. Если вы не хотите задавать конкретное значение, но хотите сделать параметр необязательным, вы можете установить значение по умолчанию равным `None`. Но если вы хотите сделать query-параметр обязательным, вы можете просто не указывать значение по умолчанию: -{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *} +{* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *} Здесь параметр запроса `needy` является обязательным параметром с типом данных `str`. diff --git a/docs/ru/docs/tutorial/request-files.md b/docs/ru/docs/tutorial/request-files.md index 9cfbd53df..41922333f 100644 --- a/docs/ru/docs/tutorial/request-files.md +++ b/docs/ru/docs/tutorial/request-files.md @@ -20,13 +20,13 @@ $ pip install python-multipart Импортируйте `File` и `UploadFile` из модуля `fastapi`: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[3] *} ## Определите параметры `File` { #define-file-parameters } Создайте параметры `File` так же, как вы это делаете для `Body` или `Form`: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} /// info | Дополнительная информация @@ -54,7 +54,7 @@ $ pip install python-multipart Определите параметр файла с типом `UploadFile`: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[14] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[14] *} Использование `UploadFile` имеет ряд преимуществ перед `bytes`: @@ -122,7 +122,7 @@ contents = myfile.file.read() Но когда форма включает файлы, она кодируется как multipart/form-data. Если вы используете `File`, **FastAPI** будет знать, что ему нужно получить файлы из нужной части тела. -Если вы хотите узнать больше об этих кодировках и полях форм, перейдите по ссылке MDN web docs for POST. +Если вы хотите узнать больше об этих кодировках и полях форм, перейдите по ссылке MDN web docs for POST. /// @@ -144,7 +144,7 @@ contents = myfile.file.read() Вы также можете использовать `File()` вместе с `UploadFile`, например, для установки дополнительных метаданных: -{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *} +{* ../../docs_src/request_files/tutorial001_03_an_py310.py hl[9,15] *} ## Загрузка нескольких файлов { #multiple-file-uploads } @@ -154,7 +154,7 @@ contents = myfile.file.read() Для этого необходимо объявить список `bytes` или `UploadFile`: -{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *} +{* ../../docs_src/request_files/tutorial002_an_py310.py hl[10,15] *} Вы получите, как и было объявлено, список `list` из `bytes` или `UploadFile`. @@ -170,7 +170,7 @@ contents = myfile.file.read() Так же, как и раньше, вы можете использовать `File()` для задания дополнительных параметров, даже для `UploadFile`: -{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *} +{* ../../docs_src/request_files/tutorial003_an_py310.py hl[11,18:20] *} ## Резюме { #recap } diff --git a/docs/ru/docs/tutorial/request-form-models.md b/docs/ru/docs/tutorial/request-form-models.md index f8c58356c..f4411a27b 100644 --- a/docs/ru/docs/tutorial/request-form-models.md +++ b/docs/ru/docs/tutorial/request-form-models.md @@ -24,7 +24,7 @@ $ pip install python-multipart Вам просто нужно объявить **Pydantic-модель** с полями, которые вы хотите получить как **поля формы**, а затем объявить параметр как `Form`: -{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *} +{* ../../docs_src/request_form_models/tutorial001_an_py310.py hl[9:11,15] *} **FastAPI** **извлечёт** данные для **каждого поля** из **данных формы** в запросе и выдаст вам объявленную Pydantic-модель. @@ -48,7 +48,7 @@ $ pip install python-multipart Вы можете сконфигурировать Pydantic-модель так, чтобы запретить (`forbid`) все дополнительные (`extra`) поля: -{* ../../docs_src/request_form_models/tutorial002_an_py39.py hl[12] *} +{* ../../docs_src/request_form_models/tutorial002_an_py310.py hl[12] *} Если клиент попробует отправить дополнительные данные, то в ответ он получит **ошибку**. diff --git a/docs/ru/docs/tutorial/request-forms-and-files.md b/docs/ru/docs/tutorial/request-forms-and-files.md index 691dc75ba..10836d74f 100644 --- a/docs/ru/docs/tutorial/request-forms-and-files.md +++ b/docs/ru/docs/tutorial/request-forms-and-files.md @@ -16,13 +16,13 @@ $ pip install python-multipart ## Импортируйте `File` и `Form` { #import-file-and-form } -{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[3] *} ## Определите параметры `File` и `Form` { #define-file-and-form-parameters } Создайте параметры файла и формы таким же образом, как для `Body` или `Query`: -{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[10:12] *} Файлы и поля формы будут загружены в виде данных формы, и вы получите файлы и поля формы. diff --git a/docs/ru/docs/tutorial/request-forms.md b/docs/ru/docs/tutorial/request-forms.md index e257652b6..01f71ac2f 100644 --- a/docs/ru/docs/tutorial/request-forms.md +++ b/docs/ru/docs/tutorial/request-forms.md @@ -18,17 +18,17 @@ $ pip install python-multipart Импортируйте `Form` из `fastapi`: -{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[3] *} ## Определение параметров `Form` { #define-form-parameters } Создайте параметры формы так же, как это делается для `Body` или `Query`: -{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *} +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[9] *} -Например, в одном из способов использования спецификации OAuth2 (называемом «потоком пароля») требуется отправить `username` и `password` в виде полей формы. +Например, в одном из способов использования спецификации OAuth2 (называемом «password flow» - аутентификация по паролю) требуется отправить `username` и `password` в виде полей формы. -spec требует, чтобы поля были строго названы `username` и `password` и отправлялись как поля формы, а не JSON. +спецификация требует, чтобы поля были строго названы `username` и `password` и отправлялись как поля формы, а не JSON. С помощью `Form` вы можете объявить те же настройки, что и с `Body` (и `Query`, `Path`, `Cookie`), включая валидацию, примеры, псевдоним (например, `user-name` вместо `username`) и т.д. @@ -56,7 +56,7 @@ $ pip install python-multipart Но когда форма содержит файлы, она кодируется как `multipart/form-data`. О работе с файлами вы прочтёте в следующей главе. -Если вы хотите узнать больше про эти кодировки и поля формы, обратитесь к MDN веб-документации для `POST`. +Если вы хотите узнать больше про эти кодировки и поля формы, обратитесь к MDN веб-документации для `POST`. /// diff --git a/docs/ru/docs/tutorial/response-model.md b/docs/ru/docs/tutorial/response-model.md index 22a811cd5..cd99ce28c 100644 --- a/docs/ru/docs/tutorial/response-model.md +++ b/docs/ru/docs/tutorial/response-model.md @@ -183,7 +183,7 @@ FastAPI делает несколько вещей внутри вместе с Самый распространённый случай — [возвращать Response напрямую, как описано далее в разделах документации для продвинутых](../advanced/response-directly.md){.internal-link target=_blank}. -{* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *} +{* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *} Этот простой случай обрабатывается FastAPI автоматически, потому что аннотация возвращаемого типа — это класс (или подкласс) `Response`. @@ -193,7 +193,7 @@ FastAPI делает несколько вещей внутри вместе с Вы также можете использовать подкласс `Response` в аннотации типа: -{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *} +{* ../../docs_src/response_model/tutorial003_03_py310.py hl[8:9] *} Это тоже сработает, так как `RedirectResponse` — подкласс `Response`, и FastAPI автоматически обработает этот простой случай. @@ -201,7 +201,7 @@ FastAPI делает несколько вещей внутри вместе с Но когда вы возвращаете произвольный объект, не являющийся валидным типом Pydantic (например, объект базы данных), и аннотируете его таким образом в функции, FastAPI попытается создать модель ответа Pydantic из этой аннотации типа и потерпит неудачу. -То же произойдёт, если у вас будет что-то вроде union разных типов, где один или несколько не являются валидными типами Pydantic, например, это приведёт к ошибке 💥: +То же произойдёт, если у вас будет что-то вроде union разных типов, где один или несколько не являются валидными типами Pydantic, например, это приведёт к ошибке 💥: {* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} diff --git a/docs/ru/docs/tutorial/response-status-code.md b/docs/ru/docs/tutorial/response-status-code.md index 30f642b64..13d982e80 100644 --- a/docs/ru/docs/tutorial/response-status-code.md +++ b/docs/ru/docs/tutorial/response-status-code.md @@ -8,7 +8,7 @@ * `@app.delete()` * и других. -{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} /// note | Примечание @@ -66,7 +66,7 @@ FastAPI знает об этом и создаст документацию Open /// tip | Подсказка -Чтобы узнать больше о HTTP кодах статуса и о том, для чего каждый из них предназначен, ознакомьтесь с MDN документацией об HTTP статус-кодах. +Чтобы узнать больше о HTTP кодах статуса и о том, для чего каждый из них предназначен, ознакомьтесь с MDN документацией об HTTP статус-кодах. /// @@ -74,7 +74,7 @@ FastAPI знает об этом и создаст документацию Open Рассмотрим предыдущий пример еще раз: -{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} `201` – это код статуса "Создано". @@ -82,7 +82,7 @@ FastAPI знает об этом и создаст документацию Open Для удобства вы можете использовать переменные из `fastapi.status`. -{* ../../docs_src/response_status_code/tutorial002_py39.py hl[1,6] *} +{* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *} Они содержат те же числовые значения, но позволяют использовать автозавершение редактора кода для выбора кода статуса: @@ -90,7 +90,7 @@ FastAPI знает об этом и создаст документацию Open /// note | Технические детали -Вы также можете использовать `from starlette import status` вместо `from fastapi import status`. +Вы также можете использовать `from starlette import status`. **FastAPI** позволяет использовать как `starlette.status`, так и `fastapi.status` исключительно для удобства разработчиков. Но поставляется fastapi.status непосредственно из Starlette. diff --git a/docs/ru/docs/tutorial/schema-extra-example.md b/docs/ru/docs/tutorial/schema-extra-example.md index e4a97c880..c7381aae2 100644 --- a/docs/ru/docs/tutorial/schema-extra-example.md +++ b/docs/ru/docs/tutorial/schema-extra-example.md @@ -74,7 +74,7 @@ OpenAPI 3.1.0 (используется начиная с FastAPI 0.99.0) доб Когда вы делаете это, примеры становятся частью внутренней **JSON Schema** для данных тела запроса. -Тем не менее, на момент написания этого Swagger UI, инструмент, отвечающий за отображение UI документации, не поддерживает показ нескольких примеров для данных в **JSON Schema**. Но ниже есть обходной путь. +Тем не менее, на момент написания этого Swagger UI, инструмент, отвечающий за отображение UI документации, не поддерживает показ нескольких примеров для данных в **JSON Schema**. Но ниже есть обходной путь. ### Специфические для OpenAPI `examples` { #openapi-specific-examples } diff --git a/docs/ru/docs/tutorial/security/first-steps.md b/docs/ru/docs/tutorial/security/first-steps.md index 983e85e66..9b9673b84 100644 --- a/docs/ru/docs/tutorial/security/first-steps.md +++ b/docs/ru/docs/tutorial/security/first-steps.md @@ -20,7 +20,7 @@ Скопируйте пример в файл `main.py`: -{* ../../docs_src/security/tutorial001_an_py39.py *} +{* ../../docs_src/security/tutorial001_an_py310.py *} ## Запуск { #run-it } @@ -132,7 +132,7 @@ OAuth2 был спроектирован так, чтобы бэкенд или При создании экземпляра класса `OAuth2PasswordBearer` мы передаем параметр `tokenUrl`. Этот параметр содержит URL, который клиент (фронтенд, работающий в браузере пользователя) будет использовать для отправки `username` и `password`, чтобы получить токен. -{* ../../docs_src/security/tutorial001_an_py39.py hl[8] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[8] *} /// tip | Подсказка @@ -170,7 +170,7 @@ oauth2_scheme(some, parameters) Теперь вы можете передать `oauth2_scheme` как зависимость с `Depends`. -{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} Эта зависимость предоставит `str`, который будет присвоен параметру `token` *функции-обработчика пути*. diff --git a/docs/ru/docs/tutorial/security/get-current-user.md b/docs/ru/docs/tutorial/security/get-current-user.md index c6bc07cc1..8388b672c 100644 --- a/docs/ru/docs/tutorial/security/get-current-user.md +++ b/docs/ru/docs/tutorial/security/get-current-user.md @@ -2,7 +2,7 @@ В предыдущей главе система безопасности (основанная на системе внедрения зависимостей) передавала *функции-обработчику пути* `token` типа `str`: -{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} Но это всё ещё не слишком полезно. diff --git a/docs/ru/docs/tutorial/security/index.md b/docs/ru/docs/tutorial/security/index.md index ebac013b6..bd8da824b 100644 --- a/docs/ru/docs/tutorial/security/index.md +++ b/docs/ru/docs/tutorial/security/index.md @@ -1,56 +1,56 @@ -# Настройка авторизации { #security } +# Безопасность { #security } Существует множество способов обеспечения безопасности, аутентификации и авторизации. -Обычно эта тема является достаточно сложной и трудной. +Обычно эта тема является достаточно сложной и «трудной». -Во многих фреймворках и системах только работа с определением доступов к приложению и аутентификацией требует значительных затрат усилий и написания множества кода (во многих случаях его объём может составлять более 50% от всего написанного кода). +Во многих фреймворках и системах только работа с безопасностью и аутентификацией требует значительных затрат усилий и написания множества кода (во многих случаях его объём может составлять 50% или более от всего написанного кода). -**FastAPI** предоставляет несколько инструментов, которые помогут вам настроить **Авторизацию** легко, быстро, стандартным способом, без необходимости изучать все её тонкости. +**FastAPI** предоставляет несколько инструментов, которые помогут вам работать с **безопасностью** легко, быстро, стандартным способом, без необходимости изучать и разбираться во всех спецификациях по безопасности. -Но сначала давайте рассмотрим некоторые небольшие концепции. +Но сначала давайте рассмотрим несколько небольших концепций. -## Куда-то торопишься? { #in-a-hurry } +## Нет времени? { #in-a-hurry } -Если вам не нужна информация о каких-либо из следующих терминов и вам просто нужно добавить защиту с аутентификацией на основе логина и пароля *прямо сейчас*, переходите к следующим главам. +Если вам не важны какие-либо из этих терминов и вам просто нужно добавить защиту с аутентификацией на основе имени пользователя и пароля прямо сейчас, переходите к следующим главам. ## OAuth2 { #oauth2 } -OAuth2 - это протокол, который определяет несколько способов обработки аутентификации и авторизации. +OAuth2 - это спецификация, которая определяет несколько способов обработки аутентификации и авторизации. -Он довольно обширен и охватывает несколько сложных вариантов использования. +Это довольно обширная спецификация, охватывающая несколько сложных вариантов использования. -OAuth2 включает в себя способы аутентификации с использованием "третьей стороны". +Она включает способы аутентификации с использованием «третьей стороны». -Это то, что используют под собой все кнопки "вход с помощью Facebook, Google, X (Twitter), GitHub" на страницах авторизации. +Именно это используется во всех системах с кнопками «войти с помощью Facebook, Google, X (Twitter), GitHub». ### OAuth 1 { #oauth-1 } -Ранее использовался протокол OAuth 1, который сильно отличается от OAuth2 и является более сложным, поскольку он включал прямые описания того, как шифровать сообщение. +Ранее использовался OAuth 1, который сильно отличается от OAuth2 и является более сложным, поскольку он включал прямые спецификации того, как шифровать обмен данными. В настоящее время он не очень популярен и не используется. -OAuth2 не указывает, как шифровать сообщение, он ожидает, что ваше приложение будет обслуживаться по протоколу HTTPS. +OAuth2 не указывает, как шифровать обмен данными, он ожидает, что ваше приложение будет обслуживаться по протоколу HTTPS. /// tip | Подсказка -В разделе **Развертывание** вы увидите как настроить протокол HTTPS бесплатно, используя Traefik и Let's Encrypt. +В разделе о **развертывании** вы увидите, как настроить HTTPS бесплатно, используя Traefik и Let's Encrypt. /// ## OpenID Connect { #openid-connect } -OpenID Connect - это еще один протокол, основанный на **OAuth2**. +OpenID Connect — это ещё одна спецификация, основанная на **OAuth2**. -Он просто расширяет OAuth2, уточняя некоторые вещи, не имеющие однозначного определения в OAuth2, в попытке сделать его более совместимым. +Она просто расширяет OAuth2, уточняя некоторые вещи, которые относительно неоднозначны в OAuth2, стараясь сделать его более совместимым. -Например, для входа в Google используется OpenID Connect (который под собой использует OAuth2). +Например, для входа в Google используется OpenID Connect (который под капотом использует OAuth2). Но вход в Facebook не поддерживает OpenID Connect. У него есть собственная вариация OAuth2. -### OpenID (не "OpenID Connect") { #openid-not-openid-connect } +### OpenID (не «OpenID Connect») { #openid-not-openid-connect } -Также ранее использовался стандарт "OpenID", который пытался решить ту же проблему, что и **OpenID Connect**, но не был основан на OAuth2. +Также ранее использовалась спецификация «OpenID», которая пыталась решить ту же задачу, что и **OpenID Connect**, но не была основана на OAuth2. Таким образом, это была полноценная дополнительная система. @@ -62,45 +62,45 @@ OpenAPI (ранее известный как Swagger) - это открытая **FastAPI** основан на **OpenAPI**. -Это то, что делает возможным наличие множества автоматических интерактивных интерфейсов документирования, сгенерированного кода и т.д. +Это то, что делает возможными несколько автоматических интерактивных интерфейсов документации, генерацию кода и т.д. -В OpenAPI есть способ использовать несколько "схем" безопасности. +В OpenAPI есть способ определить несколько «схем» безопасности. -Таким образом, вы можете воспользоваться преимуществами Всех этих стандартных инструментов, включая интерактивные системы документирования. +Используя их, вы можете воспользоваться преимуществами всех этих инструментов, основанных на стандартах, включая интерактивные системы документирования. -OpenAPI может использовать следующие схемы авторизации: +OpenAPI определяет следующие схемы безопасности: -* `apiKey`: уникальный идентификатор для приложения, который может быть получен из: - * Параметров запроса. - * Заголовка. - * Cookies. -* `http`: стандартные системы аутентификации по протоколу HTTP, включая: - * `bearer`: заголовок `Authorization` со значением `Bearer {уникальный токен}`. Это унаследовано от OAuth2. - * Базовая аутентификация по протоколу HTTP. +* `apiKey`: специфичный для приложения ключ, который может поступать из: + * параметра запроса. + * HTTP-заголовка. + * cookie. +* `http`: стандартные системы аутентификации по HTTP, включая: + * `bearer`: HTTP-заголовок `Authorization` со значением `Bearer ` плюс токен. Это унаследовано от OAuth2. + * Базовая аутентификация по HTTP. * HTTP Digest и т.д. -* `oauth2`: все способы обеспечения безопасности OAuth2 называемые "потоки" (англ. "flows"). - * Некоторые из этих "потоков" подходят для реализации аутентификации через сторонний сервис использующий OAuth 2.0 (например, Google, Facebook, X (Twitter), GitHub и т.д.): +* `oauth2`: все способы OAuth2 для обеспечения безопасности (называются «потоками»). + * Несколько из этих «потоков» подходят для построения провайдера аутентификации OAuth 2.0 (например, Google, Facebook, X (Twitter), GitHub и т.д.): * `implicit` * `clientCredentials` * `authorizationCode` - * Но есть один конкретный "поток", который может быть идеально использован для обработки аутентификации непосредственно в том же приложении: - * `password`: в некоторых следующих главах будут рассмотрены примеры этого. -* `openIdConnect`: способ определить, как автоматически обнаруживать данные аутентификации OAuth2. - * Это автоматическое обнаружение определено в спецификации OpenID Connect. + * Но есть один конкретный «поток», который можно идеально использовать для обработки аутентификации непосредственно в этом же приложении: + * `password`: в некоторых следующих главах будут приведены примеры. +* `openIdConnect`: имеет способ определить, как автоматически обнаруживать данные аутентификации OAuth2. + * Именно это автоматическое обнаружение определено в спецификации OpenID Connect. /// tip | Подсказка -Интеграция сторонних сервисов для аутентификации/авторизации таких как Google, Facebook, X (Twitter), GitHub и т.д. осуществляется достаточно легко. +Интеграция сторонних провайдеров аутентификации/авторизации, таких как Google, Facebook, X (Twitter), GitHub и т.д., также возможна и относительно проста. -Самой сложной проблемой является создание такого провайдера аутентификации/авторизации, но **FastAPI** предоставляет вам инструменты, позволяющие легко это сделать, выполняя при этом всю тяжелую работу за вас. +Самой сложной задачей является создание такого провайдера аутентификации/авторизации, но **FastAPI** предоставляет вам инструменты, позволяющие легко это сделать, выполняя при этом всю тяжёлую работу за вас. /// -## Преимущества **FastAPI** { #fastapi-utilities } +## Инструменты **FastAPI** { #fastapi-utilities } -Fast API предоставляет несколько инструментов для каждой из этих схем безопасности в модуле `fastapi.security`, которые упрощают использование этих механизмов безопасности. +FastAPI предоставляет несколько инструментов для каждой из этих схем безопасности в модуле `fastapi.security`, которые упрощают использование этих механизмов безопасности. -В следующих главах вы увидите, как обезопасить свой API, используя инструменты, предоставляемые **FastAPI**. +В следующих главах вы увидите, как добавить безопасность в ваш API, используя инструменты, предоставляемые **FastAPI**. -И вы также увидите, как он автоматически интегрируется в систему интерактивной документации. +И вы также увидите, как это автоматически интегрируется в систему интерактивной документации. diff --git a/docs/ru/docs/tutorial/security/oauth2-jwt.md b/docs/ru/docs/tutorial/security/oauth2-jwt.md index 803491f53..7838b07df 100644 --- a/docs/ru/docs/tutorial/security/oauth2-jwt.md +++ b/docs/ru/docs/tutorial/security/oauth2-jwt.md @@ -1,10 +1,10 @@ # OAuth2 с паролем (и хешированием), Bearer с JWT-токенами { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens } -Теперь, когда у нас определен процесс обеспечения безопасности, давайте сделаем приложение действительно безопасным, используя токены JWT и безопасное хеширование паролей. +Теперь, когда у нас определен процесс обеспечения безопасности, давайте сделаем приложение действительно безопасным, используя токены JWT и безопасное хеширование паролей. Этот код можно реально использовать в своем приложении, сохранять хэши паролей в базе данных и т.д. -Мы продолжим разбираться, начиная с того места, на котором остановились в предыдущей главе. +Мы продолжим разбираться, начиная с того места, на котором остановились в предыдущей главе, и расширим его. ## Про JWT { #about-jwt } @@ -43,9 +43,11 @@ $ pip install pyjwt /// info | Дополнительная информация + Если вы планируете использовать алгоритмы цифровой подписи, такие как RSA или ECDSA, вам следует установить зависимость библиотеки криптографии `pyjwt[crypto]`. Подробнее об этом можно прочитать в документации по установке PyJWT. + /// ## Хеширование паролей { #password-hashing } @@ -83,11 +85,13 @@ $ pip install "pwdlib[argon2]" /// tip | Подсказка + С помощью `pwdlib` можно даже настроить его на чтение паролей, созданных **Django**, плагином безопасности **Flask** или многими другими библиотеками. Таким образом, вы сможете, например, совместно использовать одни и те же данные из приложения Django в базе данных с приложением FastAPI. Или постепенно мигрировать Django-приложение, используя ту же базу данных. При этом пользователи смогут одновременно входить в систему как из приложения Django, так и из приложения **FastAPI**. + /// ## Хеширование и проверка паролей { #hash-and-verify-the-passwords } @@ -97,11 +101,13 @@ $ pip install "pwdlib[argon2]" Создайте экземпляр PasswordHash с рекомендованными настройками — он будет использоваться для хэширования и проверки паролей. /// tip | Подсказка + pwdlib также поддерживает алгоритм хеширования bcrypt, но не включает устаревшие алгоритмы — для работы с устаревшими хэшами рекомендуется использовать библиотеку passlib. Например, вы можете использовать ее для чтения и проверки паролей, сгенерированных другой системой (например, Django), но хэшировать все новые пароли другим алгоритмом, например Argon2 или Bcrypt. И при этом быть совместимым со всеми этими системами. + /// Создайте служебную функцию для хэширования пароля, поступающего от пользователя. @@ -110,10 +116,16 @@ pwdlib также поддерживает алгоритм хешировани И еще одну — для аутентификации и возврата пользователя. -{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,51,58:59,62:63,72:79] *} + +Когда `authenticate_user` вызывается с именем пользователя, которого нет в базе данных, мы все равно запускаем `verify_password` с использованием фиктивного хэша. + +Это гарантирует, что эндпоинт отвечает примерно за одно и то же время вне зависимости от того, существует имя пользователя или нет, предотвращая тайминговые атаки (атака по времени), с помощью которых можно было бы перечислять существующие имена пользователей. /// note | Технические детали + Если проверить новую (фальшивую) базу данных `fake_users_db`, то можно увидеть, как теперь выглядит хэшированный пароль: `"$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc"`. + /// ## Работа с JWT токенами { #handle-jwt-tokens } @@ -144,7 +156,7 @@ $ openssl rand -hex 32 Создайте служебную функцию для генерации нового токена доступа. -{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,82:90] *} ## Обновление зависимостей { #update-the-dependencies } @@ -154,7 +166,7 @@ $ openssl rand -hex 32 Если токен недействителен, то сразу же верните HTTP-ошибку. -{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} ## Обновление *операции пути* `/token` { #update-the-token-path-operation } @@ -162,7 +174,7 @@ $ openssl rand -hex 32 Создайте реальный токен доступа JWT и верните его -{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[121:136] *} ### Технические подробности о JWT ключе `sub` { #technical-details-about-the-jwt-subject-sub } @@ -202,7 +214,9 @@ Username: `johndoe` Password: `secret` /// check | Проверка + Обратите внимание, что нигде в коде не используется открытый текст пароля "`secret`", мы используем только его хэшированную версию. + /// @@ -225,7 +239,9 @@ Password: `secret` /// note | Техническая информация + Обратите внимание на HTTP-заголовок `Authorization`, значение которого начинается с `Bearer `. + /// ## Продвинутое использование `scopes` { #advanced-usage-with-scopes } diff --git a/docs/ru/docs/tutorial/security/simple-oauth2.md b/docs/ru/docs/tutorial/security/simple-oauth2.md index 36ff32c8e..4b86a4013 100644 --- a/docs/ru/docs/tutorial/security/simple-oauth2.md +++ b/docs/ru/docs/tutorial/security/simple-oauth2.md @@ -236,7 +236,7 @@ UserInDB( -Если щёлкнуть на значке замка и выйти из системы, а затем попытаться выполнить ту же операцию ещё раз, будет выдана ошибка HTTP 401: +Если щёлкнуть на значке замка и выйти из системы, а затем попробовать выполнить ту же операцию ещё раз, будет выдана ошибка HTTP 401: ```JSON { diff --git a/docs/ru/docs/tutorial/sql-databases.md b/docs/ru/docs/tutorial/sql-databases.md index 1d0346533..ed67739cc 100644 --- a/docs/ru/docs/tutorial/sql-databases.md +++ b/docs/ru/docs/tutorial/sql-databases.md @@ -8,7 +8,7 @@ /// tip | Подсказка -Вы можете использовать любую другую библиотеку для работы с SQL или NoSQL базами данных (иногда их называют "ORMs"), FastAPI ничего не навязывает. 😎 +Вы можете использовать любую другую библиотеку для работы с SQL или NoSQL базами данных (иногда их называют "ORMs"), FastAPI ничего не навязывает. 😎 /// @@ -344,7 +344,7 @@ $ fastapi dev main.py -Если вы перейдёте в UI API `/docs`, вы увидите, что он обновился: теперь при создании героя он не ожидает получить `id` от клиента и т. д. +Если вы перейдёте в UI API `/docs`, вы увидите, что он обновился: теперь при создании героя он не ожидает получить `id` от клиента и т.д.
@@ -354,4 +354,4 @@ $ fastapi dev main.py Вы можете использовать **SQLModel** для взаимодействия с SQL базой данных и упростить код с помощью *моделей данных* и *моделей-таблиц*. -Гораздо больше вы можете узнать в документации **SQLModel**, там есть более подробный мини-туториал по использованию SQLModel с **FastAPI**. 🚀 +Гораздо больше вы можете узнать в документации **SQLModel**, там есть более подробное мини-руководство по использованию SQLModel с **FastAPI**. 🚀 diff --git a/docs/ru/docs/tutorial/static-files.md b/docs/ru/docs/tutorial/static-files.md index f40cfe9b0..3b0cab831 100644 --- a/docs/ru/docs/tutorial/static-files.md +++ b/docs/ru/docs/tutorial/static-files.md @@ -7,7 +7,7 @@ * Импортируйте `StaticFiles`. * "Примонтируйте" экземпляр `StaticFiles()` к определённому пути. -{* ../../docs_src/static_files/tutorial001_py39.py hl[2,6] *} +{* ../../docs_src/static_files/tutorial001_py310.py hl[2,6] *} /// note | Технические детали diff --git a/docs/ru/docs/tutorial/testing.md b/docs/ru/docs/tutorial/testing.md index ab58429c5..6dd2fe579 100644 --- a/docs/ru/docs/tutorial/testing.md +++ b/docs/ru/docs/tutorial/testing.md @@ -30,7 +30,7 @@ $ pip install httpx Напишите простое утверждение с `assert` дабы проверить истинность Python-выражения (это тоже стандарт `pytest`). -{* ../../docs_src/app_testing/tutorial001_py39.py hl[2,12,15:18] *} +{* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *} /// tip | Подсказка @@ -76,7 +76,7 @@ $ pip install httpx В файле `main.py` находится Ваше приложение **FastAPI**: -{* ../../docs_src/app_testing/app_a_py39/main.py *} +{* ../../docs_src/app_testing/app_a_py310/main.py *} ### Файл тестов { #testing-file } @@ -92,7 +92,7 @@ $ pip install httpx Так как оба файла находятся в одной директории, для импорта объекта приложения из файла `main` в файл `test_main` Вы можете использовать относительный импорт: -{* ../../docs_src/app_testing/app_a_py39/test_main.py hl[3] *} +{* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} ...и писать дальше тесты, как и раньше. @@ -119,7 +119,7 @@ $ pip install httpx Ещё есть операция `POST`, и она может вернуть несколько ошибок. -Обе *операции пути* требуют наличия в запросе заголовка `X-Token`. +Обе *операции пути* требуют наличия в запросе HTTP-заголовка `X-Token`. {* ../../docs_src/app_testing/app_b_an_py310/main.py *} @@ -139,7 +139,7 @@ $ pip install httpx * Передаёте *path*-параметры или *query*-параметры, вписав их непосредственно в строку URL. * Передаёте JSON в теле запроса, передав Python-объект (например: `dict`) через именованный параметр `json`. * Если же Вам необходимо отправить *форму с данными* вместо JSON, то используйте параметр `data` вместо `json`. -* Для передачи *заголовков*, передайте объект `dict` через параметр `headers`. +* Для передачи *HTTP-заголовков*, передайте объект `dict` через параметр `headers`. * Для передачи *cookies* также передайте `dict`, но через параметр `cookies`. Для получения дополнительной информации о передаче данных на бэкенд с помощью `httpx` или `TestClient` ознакомьтесь с документацией HTTPX. diff --git a/docs/ru/docs/virtual-environments.md b/docs/ru/docs/virtual-environments.md index 43136298a..f931cc3c8 100644 --- a/docs/ru/docs/virtual-environments.md +++ b/docs/ru/docs/virtual-environments.md @@ -53,7 +53,7 @@ $ cd awesome-project ## Создание виртуального окружения { #create-a-virtual-environment } -Когда вы начинаете работать над Python‑проектом **впервые**, создайте виртуальное окружение **внутри вашего проекта**. +Когда вы начинаете работать над Python‑проектом **впервые**, создайте виртуальное окружение **внутри вашего проекта**. /// tip | Подсказка @@ -166,7 +166,7 @@ $ source .venv/Scripts/activate Каждый раз, когда вы устанавливаете **новый пакет** в это окружение, **активируйте** окружение снова. -Это гарантирует, что если вы используете **программу терминала (CLI)**, установленную этим пакетом, вы будете использовать именно ту, что из вашего виртуального окружения, а не какую‑то глобально установленную, возможно другой версии, чем вам нужна. +Это гарантирует, что если вы используете **программу терминала (CLI)**, установленную этим пакетом, вы будете использовать именно ту, что из вашего виртуального окружения, а не какую‑то глобально установленную, возможно другой версии, чем вам нужна. ///