mirror of https://github.com/tiangolo/fastapi.git
🌐 Add Russian translation for `docs/ru/docs/tutorial/dependencies/index.md` (#11223)
This commit is contained in:
parent
7b957e94e3
commit
299bf22ad8
|
|
@ -0,0 +1,350 @@
|
|||
# Зависимости
|
||||
|
||||
**FastAPI** имеет очень мощную и интуитивную систему **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>**.
|
||||
|
||||
Она проектировалась таким образом, чтобы быть простой в использовании и облегчить любому разработчику интеграцию других компонентов с **FastAPI**.
|
||||
|
||||
## Что такое "Dependency Injection" (инъекция зависимости)
|
||||
|
||||
**"Dependency Injection"** в программировании означает, что у вашего кода (в данном случае, вашей *функции обработки пути*) есть способы объявить вещи, которые запрашиваются для работы и использования: "зависимости".
|
||||
|
||||
И потом эта система (в нашем случае **FastAPI**) организует всё, что требуется, чтобы обеспечить ваш код этой зависимостью (сделать "инъекцию" зависимости).
|
||||
|
||||
Это очень полезно, когда вам нужно:
|
||||
|
||||
* Обеспечить общую логику (один и тот же алгоритм снова и снова).
|
||||
* Общее соединение с базой данных.
|
||||
* Обеспечение безопасности, аутентификации, запроса роли и т.п.
|
||||
* И многое другое.
|
||||
|
||||
Всё это минимизирует повторение кода.
|
||||
|
||||
## Первые шаги
|
||||
|
||||
Давайте рассмотрим очень простой пример. Он настолько простой, что на данный момент почти бесполезный.
|
||||
|
||||
Но таким способом мы можем сфокусироваться на том, как же всё таки работает система **Dependency Injection**.
|
||||
|
||||
### Создание зависимости или "зависимого"
|
||||
Давайте для начала сфокусируемся на зависимостях.
|
||||
|
||||
Это просто функция, которая может принимать все те же параметры, что и *функции обработки пути*:
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="8-9"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="8-11"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="9-12"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10+ non-Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Настоятельно рекомендуем использовать `Annotated` версию насколько это возможно.
|
||||
|
||||
```Python hl_lines="6-7"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+ non-Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
|
||||
Настоятельно рекомендуем использовать `Annotated` версию насколько это возможно.
|
||||
|
||||
```Python hl_lines="8-11"
|
||||
{!> ../../../docs_src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
**И всё.**
|
||||
|
||||
**2 строки.**
|
||||
|
||||
И теперь она той же формы и структуры, что и все ваши *функции обработки пути*.
|
||||
|
||||
Вы можете думать об *функции обработки пути* как о функции без "декоратора" (без `@app.get("/some-path")`).
|
||||
|
||||
И она может возвращать всё, что требуется.
|
||||
|
||||
В этом случае, эта зависимость ожидает:
|
||||
|
||||
* Необязательный query-параметр `q` с типом `str`
|
||||
* Необязательный query-параметр `skip` с типом `int`, и значением по умолчанию `0`
|
||||
* Необязательный query-параметр `limit` с типом `int`, и значением по умолчанию `100`
|
||||
|
||||
И в конце она возвращает `dict`, содержащий эти значения.
|
||||
|
||||
!!! Информация
|
||||
|
||||
**FastAPI** добавил поддержку для `Annotated` (и начал её рекомендовать) в версии 0.95.0.
|
||||
|
||||
Если у вас более старая версия, будут ошибки при попытке использовать `Annotated`.
|
||||
|
||||
Убедитесь, что вы [Обновили FastAPI версию](../../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} до, как минимум 0.95.1, перед тем как использовать `Annotated`.
|
||||
|
||||
### Import `Depends`
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10+ non-Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Настоятельно рекомендуем использовать `Annotated` версию насколько это возможно.
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+ non-Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Настоятельно рекомендуем использовать `Annotated` версию насколько это возможно.
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
### Объявите зависимость в "зависимом"
|
||||
|
||||
Точно так же, как вы использовали `Body`, `Query` и т.д. с вашей *функцией обработки пути* для параметров, используйте `Depends` с новым параметром:
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="13 18"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="15 20"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="16 21"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10+ non-Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Настоятельно рекомендуем использовать `Annotated` версию насколько это возможно.
|
||||
|
||||
```Python hl_lines="11 16"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+ non-Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Настоятельно рекомендуем использовать `Annotated` версию насколько это возможно.
|
||||
|
||||
```Python hl_lines="15 20"
|
||||
{!> ../../../docs_src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
`Depends` работает немного иначе. Вы передаёте в `Depends` одиночный параметр, который будет похож на функцию.
|
||||
|
||||
Вы **не вызываете его** на месте (не добавляете скобочки в конце: 👎 *your_best_func()*👎), просто передаёте как параметр в `Depends()`.
|
||||
|
||||
И потом функция берёт параметры так же, как *функция обработки пути*.
|
||||
|
||||
!!! tip "Подсказка"
|
||||
В следующей главе вы увидите, какие другие вещи, помимо функций, можно использовать в качестве зависимостей.
|
||||
|
||||
Каждый раз, когда новый запрос приходит, **FastAPI** позаботится о:
|
||||
|
||||
* Вызове вашей зависимости ("зависимого") функции с корректными параметрами.
|
||||
* Получении результата из вашей функции.
|
||||
* Назначении результата в параметр в вашей *функции обработки пути*.
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
|
||||
common_parameters(["common_parameters"])
|
||||
read_items["/items/"]
|
||||
read_users["/users/"]
|
||||
|
||||
common_parameters --> read_items
|
||||
common_parameters --> read_users
|
||||
```
|
||||
|
||||
Таким образом, вы пишете общий код один раз, и **FastAPI** позаботится о его вызове для ваших *операций с путями*.
|
||||
|
||||
!!! check "Проверка"
|
||||
Обратите внимание, что вы не создаёте специальный класс и не передаёте его куда-то в **FastAPI** для регистрации, или что-то в этом роде.
|
||||
|
||||
Вы просто передаёте это в `Depends`, и **FastAPI** знает, что делать дальше.
|
||||
|
||||
## Объединяем с `Annotated` зависимостями
|
||||
|
||||
В приведенном выше примере есть небольшое **повторение кода**.
|
||||
|
||||
Когда вам нужно использовать `common_parameters()` зависимость, вы должны написать весь параметр с аннотацией типов и `Depends()`:
|
||||
|
||||
```Python
|
||||
commons: Annotated[dict, Depends(common_parameters)]
|
||||
```
|
||||
|
||||
Но потому что мы используем `Annotated`, мы можем хранить `Annotated` значение в переменной и использовать его в нескольких местах:
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="12 16 21"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_02_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="14 18 23"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_02_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="15 19 24"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_02_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Это стандартный синтаксис python и называется "type alias", это не особенность **FastAPI**.
|
||||
|
||||
Но потому что **FastAPI** базируется на стандартах Python, включая `Annotated`, вы можете использовать этот трюк в вашем коде. 😎
|
||||
|
||||
|
||||
Зависимости продолжат работу как ожидалось, и **лучшая часть** в том, что **информация о типе будет сохранена**. Это означает, что ваш редактор кода будет корректно обрабатывать **автодополнения**, **встроенные ошибки** и так далее. То же самое относится и к инструментам, таким как `mypy`.
|
||||
|
||||
Это очень полезно, когда вы интегрируете это в **большую кодовую базу**, используя **одинаковые зависимости** снова и снова во **многих** ***операциях пути***.
|
||||
|
||||
## Использовать `async` или не `async`
|
||||
|
||||
Для зависимостей, вызванных **FastAPI** (то же самое, что и ваши *функции обработки пути*), те же правила, что приняты для определения ваших функций.
|
||||
|
||||
Вы можете использовать `async def` или обычное `def`.
|
||||
|
||||
Вы также можете объявить зависимости с `async def` внутри обычной `def` *функции обработки пути*, или `def` зависимости внутри `async def` *функции обработки пути*, и так далее.
|
||||
|
||||
Это всё не важно. **FastAPI** знает, что нужно сделать. 😎
|
||||
|
||||
!!! note "Информация"
|
||||
Если вам эта тема не знакома, прочтите [Async: *"In a hurry?"*](../../async.md){.internal-link target=_blank} раздел о `async` и `await` в документации.
|
||||
|
||||
## Интеграция с OpenAPI
|
||||
|
||||
Все заявления о запросах, валидаторы, требования ваших зависимостей (и подзависимостей) будут интегрированы в соответствующую OpenAPI-схему.
|
||||
|
||||
В интерактивной документации будет вся информация по этим зависимостям тоже:
|
||||
|
||||
<img src="/img/tutorial/dependencies/image01.png">
|
||||
|
||||
## Простое использование
|
||||
|
||||
Если вы посмотрите на фото, *функция обработки пути* объявляется каждый раз, когда вычисляется путь, и тогда **FastAPI** позаботится о вызове функции с корректными параметрами, извлекая информацию из запроса.
|
||||
|
||||
На самом деле, все (или большинство) веб-фреймворков работают по схожему сценарию.
|
||||
|
||||
Вы никогда не вызываете эти функции на месте. Их вызовет ваш фреймворк (в нашем случае, **FastAPI**).
|
||||
|
||||
С системой Dependency Injection, вы можете сообщить **FastAPI**, что ваша *функция обработки пути* "зависит" от чего-то ещё, что должно быть извлечено перед вашей *функцией обработки пути*, и **FastAPI** позаботится об извлечении и инъекции результата.
|
||||
|
||||
Другие распространённые термины для описания схожей идеи "dependency injection" являются:
|
||||
|
||||
- ресурсность
|
||||
- доставка
|
||||
- сервисность
|
||||
- инъекция
|
||||
- компонентность
|
||||
|
||||
## **FastAPI** подключаемые модули
|
||||
|
||||
Инъекции и модули могут быть построены с использованием системы **Dependency Injection**. Но на самом деле, **нет необходимости создавать новые модули**, просто используя зависимости, можно объявить бесконечное количество интеграций и взаимодействий, которые доступны вашей *функции обработки пути*.
|
||||
|
||||
И зависимости могут быть созданы очень простым и интуитивным способом, что позволяет вам просто импортировать нужные пакеты Python и интегрировать их в API функции за пару строк.
|
||||
|
||||
Вы увидите примеры этого в следующих главах о реляционных и NoSQL базах данных, безопасности и т.д.
|
||||
|
||||
## Совместимость с **FastAPI**
|
||||
|
||||
Простота Dependency Injection делает **FastAPI** совместимым с:
|
||||
|
||||
- всеми реляционными базами данных
|
||||
- NoSQL базами данных
|
||||
- внешними пакетами
|
||||
- внешними API
|
||||
- системами авторизации, аутентификации
|
||||
- системами мониторинга использования API
|
||||
- системами ввода данных ответов
|
||||
- и так далее.
|
||||
|
||||
## Просто и сильно
|
||||
|
||||
Хотя иерархическая система Dependency Injection очень проста для описания и использования, она по-прежнему очень мощная.
|
||||
|
||||
Вы можете описывать зависимости в очередь, и они уже будут вызываться друг за другом.
|
||||
|
||||
Когда иерархическое дерево построено, система **Dependency Injection** берет на себя решение всех зависимостей для вас (и их подзависимостей) и обеспечивает (инъектирует) результат на каждом шаге.
|
||||
|
||||
Например, у вас есть 4 API-эндпоинта (*операции пути*):
|
||||
|
||||
- `/items/public/`
|
||||
- `/items/private/`
|
||||
- `/users/{user_id}/activate`
|
||||
- `/items/pro/`
|
||||
|
||||
Тогда вы можете требовать разные права для каждого из них, используя зависимости и подзависимости:
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
|
||||
current_user(["current_user"])
|
||||
active_user(["active_user"])
|
||||
admin_user(["admin_user"])
|
||||
paying_user(["paying_user"])
|
||||
|
||||
public["/items/public/"]
|
||||
private["/items/private/"]
|
||||
activate_user["/users/{user_id}/activate"]
|
||||
pro_items["/items/pro/"]
|
||||
|
||||
current_user --> active_user
|
||||
active_user --> admin_user
|
||||
active_user --> paying_user
|
||||
|
||||
current_user --> public
|
||||
active_user --> private
|
||||
admin_user --> activate_user
|
||||
paying_user --> pro_items
|
||||
```
|
||||
|
||||
## Интегрировано с **OpenAPI**
|
||||
|
||||
Все эти зависимости, объявляя свои требования, также добавляют параметры, проверки и т.д. к вашим операциям *path*.
|
||||
|
||||
**FastAPI** позаботится о добавлении всего этого в схему открытого API, чтобы это отображалось в системах интерактивной документации.
|
||||
Loading…
Reference in New Issue