# Залежності { #dependencies }

**FastAPI** має дуже потужну, але інтуїтивну систему **<dfn title="також відомо як: компоненти, ресурси, провайдери, сервіси, інжектовані об'єкти">Впровадження залежностей</dfn>**.

Вона створена так, щоб бути дуже простою у використанні та щоб полегшити будь-якому розробнику інтеграцію інших компонентів з **FastAPI**.

## Що таке «Впровадження залежностей» { #what-is-dependency-injection }

У програмуванні **«Впровадження залежностей»** означає, що існує спосіб для вашого коду (у цьому випадку ваших *функцій операцій шляху*) задекларувати речі, які йому потрібні для роботи: «залежності».

А потім ця система (у цьому випадку **FastAPI**) подбає про все необхідне, щоб надати вашому коду ці потрібні залежності («інжектувати» залежності).

Це дуже корисно, коли вам потрібно:

* Мати спільну логіку (одна й та сама логіка знову і знову).
* Ділитися з’єднаннями з базою даних.
* Примусово застосовувати безпеку, автентифікацію, вимоги до ролей тощо.
* І багато іншого...

Все це з мінімізацією дублювання коду.

## Перші кроки { #first-steps }

Розгляньмо дуже простий приклад. Він буде таким простим, що поки що не дуже корисним.

Але так ми зможемо зосередитися на тому, як працює система **Впровадження залежностей**.

### Створіть залежність або «залежний» { #create-a-dependency-or-dependable }

Спочатку зосередьмося на залежності.

Це просто функція, яка може приймати ті самі параметри, що й *функція операції шляху*:

{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[8:9] *}

Ось і все.

**2 рядки**.

І вона має ту саму форму та структуру, що й усі ваші *функції операцій шляху*.

Можете думати про неї як про *функцію операції шляху* без «декоратора» (без `@app.get("/some-path")`).

І вона може повертати будь-що.

У цьому випадку ця залежність очікує:

* Необов’язковий параметр запиту `q` типу `str`.
* Необов’язковий параметр запиту `skip` типу `int`, за замовчуванням `0`.
* Необов’язковий параметр запиту `limit` типу `int`, за замовчуванням `100`.

Потім вона просто повертає `dict`, що містить ці значення.

/// note | Примітка

FastAPI додав підтримку `Annotated` (і почав її рекомендувати) у версії 0.95.0.

Якщо у вас старіша версія, ви отримаєте помилки при спробі використати `Annotated`.

Переконайтеся, що ви [Оновіть версію FastAPI](../../deployment/versions.md#upgrading-the-fastapi-versions) щонайменше до 0.95.1 перед використанням `Annotated`.

///

### Імпортуйте `Depends` { #import-depends }

{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[3] *}

### Оголосіть залежність у «залежному» { #declare-the-dependency-in-the-dependant }

Так само, як ви використовуєте `Body`, `Query` тощо з параметрами вашої *функції операції шляху*, використовуйте `Depends` з новим параметром:

{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[13,18] *}

Хоча ви використовуєте `Depends` у параметрах вашої функції так само, як `Body`, `Query` тощо, `Depends` працює трохи інакше.

Ви передаєте в `Depends` лише один параметр.

Цей параметр має бути чимось на кшталт функції.

Ви її не викликаєте безпосередньо (не додавайте дужки в кінці), ви просто передаєте її як параметр у `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** подбає про його виклик для ваших *операцій шляху*.

/// tip | Порада

Зверніть увагу, що вам не потрібно створювати спеціальний клас і передавати його кудись у **FastAPI**, щоб «зареєструвати» його чи щось подібне.

Ви просто передаєте його в `Depends`, і **FastAPI** знає, що робити далі.

///

## Спільне використання залежностей `Annotated` { #share-annotated-dependencies }

У наведених вище прикладах видно невелике **дублювання коду**.

Коли вам потрібно використати залежність `common_parameters()`, доводиться писати весь параметр з анотацією типу та `Depends()`:

```Python
commons: Annotated[dict, Depends(common_parameters)]
```

Але оскільки ми використовуємо `Annotated`, ми можемо зберегти це значення `Annotated` у змінній і використовувати його в кількох місцях:

{* ../../docs_src/dependencies/tutorial001_02_an_py310.py hl[12,16,21] *}

/// tip | Порада

Це просто стандартний Python, це називається «псевдонім типу» і насправді не є специфічним для **FastAPI**.

Але оскільки **FastAPI** базується на стандартах Python, включно з `Annotated`, ви можете використати цей трюк у своєму коді. 😎

///

Залежності продовжать працювати як очікується, і **найкраще** те, що **інформація про типи буде збережена**, а це означає, що ваш редактор зможе й надалі надавати **автозаповнення**, **помилки в рядку** тощо. Те саме і для інших інструментів, як-от `mypy`.

Це буде особливо корисно у **великій кодовій базі**, де ви використовуєте **одні й ті ж залежності** знову і знову в **багатьох *операціях шляху***.

## Бути `async` чи не бути `async` { #to-async-or-not-to-async }

Оскільки залежності також викликатимуться **FastAPI** (так само, як і ваші *функції операцій шляху*), під час визначення ваших функцій діють ті самі правила.

Ви можете використовувати `async def` або звичайний `def`.

І ви можете оголошувати залежності з `async def` всередині звичайних *функцій операцій шляху* з `def`, або залежності з `def` всередині *функцій операцій шляху* з `async def` тощо.

Це не має значення. **FastAPI** знатиме, що робити.

/// note | Примітка

Якщо ви не впевнені, перегляньте розділ [Async: *"In a hurry?"*](../../async.md#in-a-hurry) про `async` і `await` у документації.

///

## Інтегровано з OpenAPI { #integrated-with-openapi }

Усі декларації запитів, перевірки та вимоги ваших залежностей (і субзалежностей) будуть інтегровані в ту саму схему OpenAPI.

Тож інтерактивна документація також міститиме всю інформацію з цих залежностей:

<img src="/img/tutorial/dependencies/image01.png">

## Просте використання { #simple-usage }

Якщо придивитися, *функції операцій шляху* оголошуються для використання щоразу, коли збігаються *шлях* та *операція*, а потім **FastAPI** подбає про виклик функції з правильними параметрами, витягуючи дані із запиту.

Насправді всі (або більшість) вебфреймворків працюють так само.

Ви ніколи не викликаєте ці функції безпосередньо. Їх викликає ваш фреймворк (у цьому випадку **FastAPI**).

За допомогою системи впровадження залежностей ви також можете вказати **FastAPI**, що ваша *функція операції шляху* також «залежить» від чогось, що має бути виконано до вашої *функції операції шляху*, і **FastAPI** подбає про виконання цього та «інжектування» результатів.

Інші поширені терміни для цієї самої ідеї «впровадження залежностей»:

* ресурси
* провайдери
* сервіси
* інжектовані об’єкти
* компоненти

## Плагіни **FastAPI** { #fastapi-plug-ins }

Інтеграції та «плагіни» можна будувати за допомогою системи **Впровадження залежностей**. Але насправді **немає потреби створювати «плагіни»**, оскільки, використовуючи залежності, можна оголосити безмежну кількість інтеграцій та взаємодій, які стають доступними для ваших *функцій операцій шляху*.

І залежності можна створювати дуже просто та інтуїтивно, що дозволяє вам просто імпортувати потрібні пакунки Python і інтегрувати їх з вашими функціями API за кілька рядків коду, буквально.

Ви побачите приклади цього в наступних розділах, про реляційні та NoSQL бази даних, безпеку тощо.

## Сумісність **FastAPI** { #fastapi-compatibility }

Простота системи впровадження залежностей робить **FastAPI** сумісним з:

* усіма реляційними базами даних
* NoSQL базами даних
* зовнішніми пакунками
* зовнішніми API
* системами автентифікації та авторизації
* системами моніторингу використання API
* системами інжекції даних у відповідь
* тощо.

## Просто і потужно { #simple-and-powerful }

Хоча ієрархічна система впровадження залежностей дуже проста у визначенні та використанні, вона все ще дуже потужна.

Ви можете визначати залежності, які своєю чергою можуть визначати власні залежності.

Зрештою будується ієрархічне дерево залежностей, і система **Впровадження залежностей** подбає про розв’язання всіх цих залежностей (і їхніх субзалежностей) та надання (інжектування) результатів на кожному кроці.

Наприклад, припустімо, у вас є 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** { #integrated-with-openapi_1 }

Усі ці залежності, декларуючи свої вимоги, також додають параметри, перевірки тощо до ваших *операцій шляху*.

**FastAPI** подбає про додавання всього цього до схеми OpenAPI, щоб це відображалося в інтерактивних системах документації.
