# Залежності { #dependencies } **FastAPI** має дуже потужну, але інтуїтивну систему **Впровадження залежностей**. Вона створена так, щоб бути дуже простою у використанні та щоб полегшити будь-якому розробнику інтеграцію інших компонентів з **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`, що містить ці значення. /// info | Інформація FastAPI додав підтримку `Annotated` (і почав її рекомендувати) у версії 0.95.0. Якщо у вас старіша версія, ви отримаєте помилки при спробі використати `Annotated`. Переконайтеся, що ви [Оновіть версію FastAPI](../../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} щонайменше до 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** подбає про його виклик для ваших *операцій шляху*. /// check | Перевірте Зверніть увагу, що вам не потрібно створювати спеціальний клас і передавати його кудись у **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){.internal-link target=_blank} про `async` і `await` у документації. /// ## Інтегровано з OpenAPI { #integrated-with-openapi } Усі декларації запитів, перевірки та вимоги ваших залежностей (і субзалежностей) будуть інтегровані в ту саму схему OpenAPI. Тож інтерактивна документація також міститиме всю інформацію з цих залежностей: ## Просте використання { #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, щоб це відображалося в інтерактивних системах документації.