🌐 Update translations for uk (update-outdated)

This commit is contained in:
github-actions[bot]
2025-12-21 18:03:30 +00:00
parent e1bd9f3e33
commit a64d65910c
37 changed files with 1821 additions and 1787 deletions

View File

@@ -1,8 +1,14 @@
# FastAPI { #fastapi }
<style>
.md-content .md-typeset h1 { display: none; }
</style>
<p align="center">
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
</p>
<p align="center">
<em>Готовий до продакшину, високопродуктивний, простий у вивченні та швидкий для написання коду фреймворк</em>
<em>Фреймворк FastAPI: висока продуктивність, легко вивчати, швидко писати код, готовий до продакшину</em>
</p>
<p align="center">
<a href="https://github.com/fastapi/fastapi/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster" target="_blank">
@@ -23,44 +29,49 @@
**Документація**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
**Програмний код**: <a href="https://github.com/fastapi/fastapi" target="_blank">https://github.com/fastapi/fastapi</a>
**Вихідний код**: <a href="https://github.com/fastapi/fastapi" target="_blank">https://github.com/fastapi/fastapi</a>
---
FastAPI - це сучасний, швидкий (високопродуктивний), вебфреймворк для створення API за допомогою Python,в основі якого лежить стандартна анотація типів Python.
FastAPI це сучасний, швидкий (високопродуктивний) вебфреймворк для створення API за допомогою Python, що базується на стандартних підказках типів Python.
Ключові особливості:
* **Швидкий**: Дуже висока продуктивність, на рівні з **NodeJS** та **Go** (завдяки Starlette та Pydantic). [Один із найшвидших фреймворків](#performance).
* **Швидкий**: дуже висока продуктивність, на рівні з **NodeJS** та **Go** (завдяки Starlette та Pydantic). [Один із найшвидших Python-фреймворків](#performance).
* **Швидке написання коду**: пришвидшує розробку функціоналу приблизно на 200%300%. *
* **Менше помилок**: зменшує приблизно на 40% кількість помилок, спричинених людиною (розробником). *
* **Інтуїтивний**: чудова підтримка редакторами коду. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Автодоповнення</abbr> всюди. Менше часу на налагодження.
* **Простий**: спроєктований так, щоб бути простим у використанні та вивченні. Менше часу на читання документації.
* **Короткий**: мінімізує дублювання коду. Кілька можливостей з кожного оголошення параметра. Менше помилок.
* **Надійний**: ви отримуєте код, готовий до продакшину. З автоматичною інтерактивною документацією.
* **Заснований на стандартах**: базується на (і повністю сумісний з) відкритими стандартами для API: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (раніше відомий як Swagger) та <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
* **Швидке написання коду**: Пришвидшує розробку функціоналу приблизно на 200%-300%. *
* **Менше помилок**: Зменшить кількість помилок спричинених людиною (розробником) на 40%. *
* **Інтуїтивний**: Чудова підтримка редакторами коду. <abbr title="Також відоме як auto-complete, autocompletion, IntelliSense.">Доповнення</abbr> всюди. Зменште час на налагодження.
* **Простий**: Спроектований, для легкого використання та навчання. Знадобиться менше часу на читання документації.
* **Короткий**: Зведе до мінімуму дублювання коду. Кожен оголошений параметр може виконувати кілька функцій.
* **Надійний**: Ви матимете стабільний код готовий до продакшину з автоматичною інтерактивною документацією.
* **Стандартизований**: Оснований та повністю сумісний з відкритими стандартами для API: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (попередньо відомий як Swagger) та <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
<small>* оцінка на основі тестів, проведених внутрішньою командою розробників, що створює продакшн-застосунки.</small>
<small>* оцінка на основі тестів внутрішньої команди розробників, створення продуктових застосунків.</small>
## Спонсори
## Спонсори { #sponsors }
<!-- sponsors -->
{% if sponsors %}
### Ключовий спонсор { #keystone-sponsor }
{% for sponsor in sponsors.keystone -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor -%}
### Золоті та срібні спонсори { #gold-and-silver-sponsors }
{% for sponsor in sponsors.gold -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor -%}
{%- for sponsor in sponsors.silver -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor %}
{% endif %}
<!-- /sponsors -->
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Other sponsors</a>
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Інші спонсори</a>
## Враження
## Враження { #opinions }
"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
@@ -88,7 +99,7 @@ FastAPI - це сучасний, швидкий (високопродуктив
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
---
@@ -100,50 +111,48 @@ FastAPI - це сучасний, швидкий (високопродуктив
---
## **Typer**, FastAPI CLI
"_If anyone is looking to build a production Python API, I would highly recommend **FastAPI**. It is **beautifully designed**, **simple to use** and **highly scalable**, it has become a **key component** in our API first development strategy and is driving many automations and services such as our Virtual TAC Engineer._"
<div style="text-align: right; margin-right: 10%;">Deon Pillsbury - <strong>Cisco</strong> <a href="https://www.linkedin.com/posts/deonpillsbury_cisco-cx-python-activity-6963242628536487936-trAp/" target="_blank"><small>(ref)</small></a></div>
---
## **Typer**, FastAPI для CLI { #typer-the-fastapi-of-clis }
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
Створюючи <abbr title="Command Line Interface">CLI</abbr> застосунок для використання в терміналі, замість веб-API зверніть увагу на <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
Якщо ви створюєте застосунок <abbr title="Command Line Interface">CLI</abbr> для використання в терміналі замість веб-API, зверніть увагу на <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
**Typer** є молодшим братом FastAPI. І це **FastAPI для CLI**. ⌨️ 🚀
**Typer** молодший брат FastAPI. І його задумано як **FastAPI для CLI**. ⌨️ 🚀
## Вимоги
## Вимоги { #requirements }
FastAPI стоїть на плечах гігантів:
* <a href="https://www.starlette.dev/" class="external-link" target="_blank">Starlette</a> для web частини.
* <a href="https://www.starlette.dev/" class="external-link" target="_blank">Starlette</a> для вебчастини.
* <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> для частини даних.
## Вставновлення
## Встановлення { #installation }
Створіть і активуйте <a href="https://fastapi.tiangolo.com/virtual-environments/" class="external-link" target="_blank">віртуальне середовище</a>, а потім встановіть FastAPI:
<div class="termy">
```console
$ pip install fastapi
$ pip install "fastapi[standard]"
---> 100%
```
</div>
Вам також знадобиться сервер ASGI для продакшину, наприклад <a href="https://www.uvicorn.dev" class="external-link" target="_blank">Uvicorn</a> або <a href="https://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
**Примітка**: переконайтеся, що ви взяли `"fastapi[standard]"` у лапки, щоб це працювало в усіх терміналах.
<div class="termy">
## Приклад { #example }
```console
$ pip install uvicorn[standard]
### Створіть { #create-it }
---> 100%
```
</div>
## Приклад
### Створіть
* Створіть файл `main.py` з:
Створіть файл `main.py` з:
```Python
from typing import Union
@@ -188,22 +197,35 @@ async def read_item(item_id: int, q: Union[str, None] = None):
**Примітка**:
Стикнувшись з проблемами, не зайвим буде ознайомитися з розділом _"In a hurry?"_ про <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` та `await` у документації</a>.
Якщо ви не знаєте, перегляньте розділ _"In a hurry?"_ про <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` та `await` у документації</a>.
</details>
### Запустіть
### Запустіть { #run-it }
Запустіть server з:
Запустіть сервер за допомогою:
<div class="termy">
```console
$ uvicorn main:app --reload
$ fastapi dev main.py
╭────────── FastAPI CLI - Development mode ───────────╮
│ │
│ Serving at: http://127.0.0.1:8000 │
│ │
│ API docs: http://127.0.0.1:8000/docs │
│ │
│ Running in development mode, for production use: │
│ │
│ fastapi run │
│ │
╰─────────────────────────────────────────────────────╯
INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp']
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [28720]
INFO: Started server process [28722]
INFO: Started reloader process [2248755] using WatchFiles
INFO: Started server process [2248757]
INFO: Waiting for application startup.
INFO: Application startup complete.
```
@@ -211,21 +233,21 @@ INFO: Application startup complete.
</div>
<details markdown="1">
<summary>Про команди <code>uvicorn main:app --reload</code>...</summary>
<summary>Про команду <code>fastapi dev main.py</code>...</summary>
Команда `uvicorn main:app` посилається на:
Команда `fastapi dev` читає ваш файл `main.py`, знаходить у ньому застосунок **FastAPI** і запускає сервер за допомогою <a href="https://www.uvicorn.dev" class="external-link" target="_blank">Uvicorn</a>.
* `main`: файл `main.py` ("Модуль" Python).
* `app`: об’єкт створений усередині `main.py` рядком `app = FastAPI()`.
* `--reload`: перезапускає сервер після зміни коду. Використовуйте виключно для розробки.
За замовчуванням `fastapi dev` запускається з авто-перезавантаженням для локальної розробки.
Докладніше читайте в <a href="https://fastapi.tiangolo.com/fastapi-cli/" target="_blank">документації FastAPI CLI</a>.
</details>
### Перевірте
### Перевірте { #check-it }
Відкрийте браузер та введіть адресу <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
Відкрийте браузер і перейдіть на <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
Ви побачите у відповідь подібний JSON:
Ви побачите JSON-відповідь:
```JSON
{"item_id": 5, "q": "somequery"}
@@ -233,32 +255,32 @@ INFO: Application startup complete.
Ви вже створили API, який:
* Отримує HTTP запити за _шляхами_ `/` та `/items/{item_id}`.
* Отримує HTTP-запити за _шляхами_ `/` та `/items/{item_id}`.
* Обидва _шляхи_ приймають `GET` <em>операції</em> (також відомі як HTTP _методи_).
* _Шлях_ `/items/{item_id}` містить _параметр шляху_ `item_id` який має бути типу `int`.
* _Шлях_ `/items/{item_id}` містить _параметр шляху_ `item_id`, який має бути типу `int`.
* _Шлях_ `/items/{item_id}` містить необовʼязковий `str` _параметр запиту_ `q`.
### Інтерактивні документації API
### Інтерактивна документація API { #interactive-api-docs }
Перейдемо сюди <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
Тепер перейдіть на <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
Ви побачите автоматичну інтерактивну API документацію (створену завдяки <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
Ви побачите автоматичну інтерактивну документацію API (надану <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### Альтернативні документації API
### Альтернативна документація API { #alternative-api-docs }
Тепер перейдемо сюди <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
А тепер перейдіть на <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
Ви побачите альтернативну автоматичну документацію (створену завдяки <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
Ви побачите альтернативну автоматичну документацію (надану <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
## Приклад оновлення
## Приклад оновлення { #example-upgrade }
Тепер модифікуйте файл `main.py`, щоб отримати вміст запиту `PUT`.
Тепер змініть файл `main.py`, щоб отримувати тіло `PUT`-запиту.
Оголошуйте вміст запиту за допомогою стандартних типів Python завдяки Pydantic.
Оголосіть тіло, використовуючи стандартні типи Python, завдяки Pydantic.
```Python hl_lines="4 9-12 25-27"
from typing import Union
@@ -290,41 +312,41 @@ def update_item(item_id: int, item: Item):
return {"item_name": item.name, "item_id": item_id}
```
Сервер повинен автоматично перезавантажуватися (тому що Ви додали `--reload` до `uvicorn` команди вище).
Сервер `fastapi dev` має автоматично перезавантажитися.
### Оновлення інтерактивної API документації
### Оновлення інтерактивної документації API { #interactive-api-docs-upgrade }
Тепер перейдемо сюди <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
Тепер перейдіть на <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
* Інтерактивна документація API буде автоматично оновлена, включаючи новий вміст:
* Інтерактивна документація API буде автоматично оновлена, включно з новим тілом:
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
* Натисніть кнопку "Try it out", це дозволить вам заповнити параметри та безпосередньо взаємодіяти з API:
* Натисніть кнопку "Try it out", вона дозволяє заповнити параметри та безпосередньо взаємодіяти з API:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png)
* Потім натисніть кнопку "Execute", інтерфейс користувача зв'яжеться з вашим API, надішле параметри, у відповідь отримає результати та покаже їх на екрані:
* Потім натисніть кнопку "Execute", інтерфейс користувача зв'яжеться з вашим API, надішле параметри, отримає результати та покаже їх на екрані:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png)
### Оновлення альтернативної API документації
### Оновлення альтернативної документації API { #alternative-api-docs-upgrade }
Зараз перейдемо <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
А тепер перейдіть на <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
* Альтернативна документація також показуватиме новий параметр і вміст запиту:
* Альтернативна документація також відобразить новий параметр запиту та тіло:
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### Підсумки
### Підсумки { #recap }
Таким чином, Ви **один раз** оголошуєте типи параметрів, тіла тощо, як параметри функції.
Отже, ви оголошуєте **один раз** типи параметрів, тіла тощо як параметри функції.
Ви робите це за допомогою стандартних сучасних типів Python.
Вам не потрібно вивчати новий синтаксис, методи чи класи конкретної бібліотеки тощо.
Використовуючи стандартний **Python**.
Лише стандартний **Python**.
Наприклад, для `int`:
@@ -332,35 +354,35 @@ def update_item(item_id: int, item: Item):
item_id: int
```
або для більш складної моделі `Item`:
або для складнішої моделі `Item`:
```Python
item: Item
```
...і з цим єдиним оголошенням Ви отримуєте:
...і з цим єдиним оголошенням ви отримуєте:
* Підтримку редактора, включаючи:
* Варіанти заповнення.
* Перевірку типів.
* Перевірку даних:
* Автоматичні та зрозумілі помилки, у разі некоректних даних.
* Перевірка навіть для JSON з високим рівнем вкладеності.
* <abbr title="також відомий як: serialization, parsing, marshalling">Перетворення</abbr> вхідних даних: з мережі до даних і типів Python. Читання з:
* Підтримку редактора, включно з:
* Автодоповненням.
* Перевіркою типів.
* Валідацію даних:
* Автоматичні та зрозумілі помилки, коли дані некоректні.
* Валідацію навіть для глибоко вкладених JSON-обʼєктів.
* <abbr title="also known as: serialization, parsing, marshalling">Перетворення</abbr> вхідних даних: з мережі до даних і типів Python. Читання з:
* JSON.
* Параметрів шляху.
* Параметрів запиту.
* Cookies.
* Headers.
* Forms.
* Файлів.
* <abbr title="також відомий як: serialization, parsing, marshalling">Перетворення</abbr> вихідних даних: з типів і даних Python до мережевих даних (як JSON):
* Конвертація Python типів (`str`, `int`, `float`, `bool`, `list`, тощо).
* `datetime` об'єкти.
* `UUID` об'єкти.
* Моделі бази даних.
* Files.
* <abbr title="also known as: serialization, parsing, marshalling">Перетворення</abbr> вихідних даних: перетворення з даних і типів Python у мережеві дані (як JSON):
* Перетворення типів Python (`str`, `int`, `float`, `bool`, `list`, тощо).
* Обʼєктів `datetime`.
* Обʼєктів `UUID`.
* Моделей бази даних.
* ...та багато іншого.
* Автоматичну інтерактивну документацію API, включаючи 2 альтернативні інтерфейси користувача:
* Автоматичну інтерактивну документацію API, включно з 2 альтернативними інтерфейсами користувача:
* Swagger UI.
* ReDoc.
@@ -368,26 +390,26 @@ item: Item
Повертаючись до попереднього прикладу коду, **FastAPI**:
* Підтвердить наявність `item_id` у шляху для запитів `GET` та `PUT`.
* Підтвердить, що `item_id` має тип `int` для запитів `GET` and `PUT`.
* Перевірить, що `item_id` є у шляху для `GET` та `PUT`-запитів.
* Перевірить, що `item_id` має тип `int` для `GET` та `PUT`-запитів.
* Якщо це не так, клієнт побачить корисну, зрозумілу помилку.
* Перевірить, чи є необов'язковий параметр запиту з назвою `q` (а саме `http://127.0.0.1:8000/items/foo?q=somequery`) для запитів `GET`.
* Перевірить, чи є необов'язковий параметр запиту з назвою `q` (як у `http://127.0.0.1:8000/items/foo?q=somequery`) для `GET`-запитів.
* Оскільки параметр `q` оголошено як `= None`, він необов'язковий.
* За відсутності `None` він був би обов'язковим (як і вміст у випадку з `PUT`).
* Для запитів `PUT` із `/items/{item_id}`, читає вміст як JSON:
* Перевірить, чи має обов'язковий атрибут `name` тип `str`.
* Перевірить, чи має обов'язковий атрибут `price` тип `float`.
* Перевірить, чи існує необов'язковий атрибут `is_offer` та чи має він тип `bool`.
* Усе це також працюватиме для глибоко вкладених об'єктів JSON.
* Автоматично конвертує із та в JSON.
* Документує все за допомогою OpenAPI, який може бути використано в:
* Без `None` він був би обов'язковим (як і тіло у випадку з `PUT`).
* Для `PUT`-запитів до `/items/{item_id}` прочитає тіло як JSON:
* Перевірить, що є обовʼязковий атрибут `name`, який має бути типу `str`.
* Перевірить, що є обовʼязковий атрибут `price`, який має бути типу `float`.
* Перевірить, що є необовʼязковий атрибут `is_offer`, який має бути типу `bool`, якщо він присутній.
* Усе це також працюватиме для глибоко вкладених JSON-обʼєктів.
* Автоматично перетворюватиме з та в JSON.
* Документуватиме все за допомогою OpenAPI, який може бути використано в:
* Інтерактивних системах документації.
* Системах автоматичної генерації клієнтського коду для багатьох мов.
* Надає безпосередньо 2 вебінтерфейси інтерактивної документації.
* Надаватиме безпосередньо 2 вебінтерфейси інтерактивної документації.
---
Ми лише трішки доторкнулися до коду, але Ви вже маєте уявлення про те, як все працює.
Ми лише трішки доторкнулися до поверхні, але ви вже маєте уявлення про те, як усе працює.
Спробуйте змінити рядок:
@@ -407,57 +429,131 @@ item: Item
... "item_price": item.price ...
```
...і побачите, як ваш редактор автоматично заповнюватиме атрибути та знатиме їхні типи:
...і побачите, як ваш редактор автоматично доповнюватиме атрибути та знатиме їхні типи:
![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)
Для більш повного ознайомлення з додатковими функціями, перегляньте <a href="https://fastapi.tiangolo.com/tutorial/">Туторіал - Посібник Користувача</a>.
Для більш повного прикладу, що включає більше можливостей, перегляньте <a href="https://fastapi.tiangolo.com/tutorial/">Туторіал Посібник користувача</a>.
**Spoiler alert**: туторіал - посібник користувача містить:
**Spoiler alert**: туторіал посібник користувача містить:
* Оголошення **параметрів** з інших місць як: **headers**, **cookies**, **form fields** та **files**.
* Як встановити **перевірку обмежень** як `maximum_length` або `regex`.
* Дуже потужна і проста у використанні система **<abbr title="також відома як: components, resources, providers, services, injectables">Ін'єкція Залежностей</abbr>**.
* Безпека та автентифікація, включаючи підтримку **OAuth2** з **JWT tokens** та **HTTP Basic** автентифікацію.
* Оголошення **параметрів** з інших різних місць, як-от: **headers**, **cookies**, **form fields** та **files**.
* Як встановлювати **обмеження валідації** як `maximum_length` або `regex`.
* Дуже потужну і просту у використанні систему **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>**.
* Безпеку та автентифікацію, включно з підтримкою **OAuth2** з **JWT tokens** та **HTTP Basic** auth.
* Досконаліші (але однаково прості) техніки для оголошення **глибоко вкладених моделей JSON** (завдяки Pydantic).
* Багато додаткових функцій (завдяки Starlette) як-от:
* Інтеграцію **GraphQL** з <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> та іншими бібліотеками.
* Багато додаткових можливостей (завдяки Starlette) як-от:
* **WebSockets**
* надзвичайно прості тести на основі HTTPX та `pytest`
* **CORS**
* **Cookie Sessions**
* ...та більше.
## Продуктивність
### Розгортання застосунку (необовʼязково) { #deploy-your-app-optional }
Незалежні тести TechEmpower показують що застосунки **FastAPI**, які працюють під керуванням Uvicorn <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">є одними з найшвидших серед доступних фреймворків в Python</a>, поступаючись лише Starlette та Uvicorn (які внутрішньо використовуються в FastAPI). (*)
За бажання ви можете розгорнути ваш застосунок FastAPI у <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>, перейдіть і приєднайтеся до списку очікування, якщо ви ще цього не зробили. 🚀
Щоб дізнатися більше про це, перегляньте розділ <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
Якщо у вас вже є обліковий запис **FastAPI Cloud** (ми запросили вас зі списку очікування 😉), ви можете розгорнути ваш застосунок однією командою.
## Необов'язкові залежності
Перед розгортанням переконайтеся, що ви ввійшли в систему:
Pydantic використовує:
<div class="termy">
```console
$ fastapi login
You are logged in to FastAPI Cloud 🚀
```
</div>
Потім розгорніть ваш застосунок:
<div class="termy">
```console
$ fastapi deploy
Deploying to FastAPI Cloud...
✅ Deployment successful!
🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev
```
</div>
Ось і все! Тепер ви можете отримати доступ до вашого застосунку за цією URL-адресою. ✨
#### Про FastAPI Cloud { #about-fastapi-cloud }
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** створено тим самим автором і командою, що стоять за **FastAPI**.
Він спрощує процес **створення**, **розгортання** та **доступу** до API з мінімальними зусиллями.
Він забезпечує той самий **developer experience** створення застосунків на FastAPI під час їх **розгортання** у хмарі. 🎉
FastAPI Cloud — основний спонсор і джерело фінансування open source проєктів *FastAPI and friends*. ✨
#### Розгортання в інших хмарних провайдерів { #deploy-to-other-cloud-providers }
FastAPI — open source і базується на стандартах. Ви можете розгортати застосунки FastAPI в будь-якому хмарному провайдері, який ви оберете.
Дотримуйтеся інструкцій вашого хмарного провайдера, щоб розгорнути застосунки FastAPI у нього. 🤓
## Продуктивність { #performance }
Незалежні тести TechEmpower показують застосунки **FastAPI**, які працюють під керуванням Uvicorn, як <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">одні з найшвидших доступних Python-фреймворків</a>, поступаючись лише Starlette та Uvicorn (які внутрішньо використовуються в FastAPI). (*)
Щоб дізнатися більше, перегляньте розділ <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
## Залежності { #dependencies }
FastAPI залежить від Pydantic і Starlette.
### Залежності `standard` { #standard-dependencies }
Коли ви встановлюєте FastAPI за допомогою `pip install "fastapi[standard]"`, ви отримуєте групу необовʼязкових залежностей `standard`:
Використовується Pydantic:
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email-validator</code></a> - для валідації електронної пошти.
* <a href="https://docs.pydantic.dev/latest/usage/pydantic_settings/" target="_blank"><code>pydantic-settings</code></a> - для управління налаштуваннями.
Використовується Starlette:
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - потрібно, якщо ви хочете використовувати `TestClient`.
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - потрібно, якщо ви хочете використовувати конфігурацію шаблонів за замовчуванням.
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - потрібно, якщо ви хочете підтримувати <abbr title="converting the string that comes from an HTTP request into Python data">«parsing»</abbr> форм за допомогою `request.form()`.
Використовується FastAPI:
* <a href="https://www.uvicorn.dev" target="_blank"><code>uvicorn</code></a> - для сервера, який завантажує та обслуговує ваш застосунок. Це включає `uvicorn[standard]`, до якого входять деякі залежності (наприклад, `uvloop`), потрібні для високопродуктивної роботи сервера.
* `fastapi-cli[standard]` - щоб надати команду `fastapi`.
* Це включає `fastapi-cloud-cli`, який дозволяє розгортати ваш застосунок FastAPI у <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>.
### Без залежностей `standard` { #without-standard-dependencies }
Якщо ви не хочете включати необовʼязкові залежності `standard`, ви можете встановити через `pip install fastapi` замість `pip install "fastapi[standard]"`.
### Без `fastapi-cloud-cli` { #without-fastapi-cloud-cli }
Якщо ви хочете встановити FastAPI зі стандартними залежностями, але без `fastapi-cloud-cli`, ви можете встановити через `pip install "fastapi[standard-no-fastapi-cloud-cli]"`.
### Додаткові необовʼязкові залежності { #additional-optional-dependencies }
Є ще деякі додаткові залежності, які ви можете захотіти встановити.
Додаткові необовʼязкові залежності Pydantic:
* <a href="https://docs.pydantic.dev/latest/usage/pydantic_settings/" target="_blank"><code>pydantic-settings</code></a> - для керування налаштуваннями.
* <a href="https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/" target="_blank"><code>pydantic-extra-types</code></a> - для додаткових типів, що можуть бути використані з Pydantic.
Додаткові необовʼязкові залежності FastAPI:
Starlette використовує:
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - потрібно, якщо ви хочете використовувати `ORJSONResponse`.
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - потрібно, якщо ви хочете використовувати `UJSONResponse`.
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - Необхідно, якщо Ви хочете використовувати `TestClient`.
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Необхідно, якщо Ви хочете використовувати шаблони як конфігурацію за замовчуванням.
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - Необхідно, якщо Ви хочете підтримувати <abbr title="перетворення рядка, який надходить із запиту HTTP, на дані Python">"розбір"</abbr> форми за допомогою `request.form()`.
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Необхідно для підтримки `SessionMiddleware`.
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - Необхідно для підтримки Starlette `SchemaGenerator` (ймовірно, вам це не потрібно з FastAPI).
FastAPI / Starlette використовують:
* <a href="https://www.uvicorn.dev" target="_blank"><code>uvicorn</code></a> - для сервера, який завантажує та обслуговує вашу програму.
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Необхідно, якщо Ви хочете використовувати `ORJSONResponse`.
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Необхідно, якщо Ви хочете використовувати `UJSONResponse`.
Ви можете встановити все це за допомогою `pip install fastapi[all]`.
## Ліцензія
## Ліцензія { #license }
Цей проєкт ліцензовано згідно з умовами ліцензії MIT.

View File

@@ -1,5 +1,5 @@
# Навчання
# Навчання { #learn }
У цьому розділі надані вступні та навчальні матеріали для вивчення FastAPI.
У цьому розділі надані вступні розділи та навчальні матеріали для вивчення **FastAPI**.
Це можна розглядати як **книгу**, **курс**, або **офіційний** та рекомендований спосіб освоїти FastAPI. 😎

View File

@@ -1,29 +1,28 @@
# Вступ до типів Python
# Вступ до типів Python { #python-types-intro }
Python підтримує додаткові "підказки типу" ("type hints") (також звані "анотаціями типу" ("type annotations")).
Python підтримує додаткові «підказки типів» (також звані «анотаціями типів»).
Ці **"type hints"** є спеціальним синтаксисом, що дозволяє оголошувати <abbr title="наприклад: str, int, float, bool">тип</abbr> змінної.
Ці **«підказки типів»** або анотації — це спеціальний синтаксис, що дозволяє оголошувати <abbr title="наприклад: str, int, float, bool">тип</abbr> змінної.
За допомогою оголошення типів для ваших змінних, редактори та інструменти можуть надати вам кращу підтримку.
За допомогою оголошення типів для ваших змінних редактори та інструменти можуть надати вам кращу підтримку.
Це просто **швидкий посібник / нагадування** про анотації типів у Python. Він покриває лише мінімум, необхідний щоб використовувати їх з **FastAPI**... що насправді дуже мало.
Це лише **швидкий туторіал / нагадування** про підказки типів у Python. Він покриває лише мінімум, необхідний щоб використовувати їх з **FastAPI**... що насправді дуже мало.
**FastAPI** повністю базується на цих анотаціях типів, вони дають йому багато переваг.
**FastAPI** повністю базується на цих підказках типів, вони дають йому багато переваг і користі.
Але навіть якщо ви ніколи не використаєте **FastAPI**, вам буде корисно дізнатись трохи про них.
/// note
/// note | Примітка
Якщо ви експерт у Python і ви вже знаєте усе про анотації типів - перейдіть до наступного розділу.
Якщо ви експерт у Python і ви вже знаєте все про підказки типів, перейдіть до наступного розділу.
///
## Мотивація
## Мотивація { #motivation }
Давайте почнемо з простого прикладу:
{* ../../docs_src/python_types/tutorial001.py *}
{* ../../docs_src/python_types/tutorial001_py39.py *}
Виклик цієї програми виводить:
@@ -34,13 +33,12 @@ John Doe
Функція виконує наступне:
* Бере `first_name` та `last_name`.
* Конвертує кожну літеру кожного слова у верхній регістр за допомогою `title()`.
* <abbr title="З’єднує їх, як одне ціле. З вмістом один за одним.">Конкатенує</abbr> їх разом із пробілом по середині.
* Перетворює першу літеру кожного з них у верхній регістр за допомогою `title()`.
* <abbr title="Об’єднує їх разом, як одне ціле. З вмістом один за одним.">Конкатенує</abbr> їх разом із пробілом по середині.
{* ../../docs_src/python_types/tutorial001.py hl[2] *}
{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *}
### Редагуйте це
### Редагуйте це { #edit-it }
Це дуже проста програма.
@@ -48,11 +46,11 @@ John Doe
У певний момент ви розпочали б визначення функції, у вас були б готові параметри...
Але тоді вам потрібно викликати "той метод, який переводить першу літеру у верхній регістр".
Але тоді вам потрібно викликати «той метод, який перетворює першу літеру у верхній регістр».
Це буде `upper`? Чи `uppercase`? `first_uppercase`? `capitalize`?
Тоді ви спробуєте давнього друга програміста - автозаповнення редактора коду.
Тоді ви спробуєте давнього друга програміста автозаповнення редактора коду.
Ви надрукуєте перший параметр функції, `first_name`, тоді крапку (`.`), а тоді натиснете `Ctrl+Space`, щоб запустити автозаповнення.
@@ -60,7 +58,7 @@ John Doe
<img src="/img/python-types/image01.png">
### Додайте типи
### Додайте типи { #add-types }
Давайте змінимо один рядок з попередньої версії.
@@ -78,10 +76,9 @@ John Doe
Ось і все.
Це "type hints":
{* ../../docs_src/python_types/tutorial002.py hl[1] *}
Це «підказки типів»:
{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *}
Це не те саме, що оголошення значень за замовчуванням, як це було б з:
@@ -91,43 +88,41 @@ John Doe
Це зовсім інше.
Ми використовуємо двокрапку (`:`), не дорівнює (`=`).
Ми використовуємо двокрапку (`:`), не знак дорівнює (`=`).
І додавання анотації типу зазвичай не змінює того, що сталось би без них.
І додавання підказок типів зазвичай не змінює того, що відбувається, порівняно з тим, що відбувалося б без них.
Але тепер, уявіть що ви посеред процесу створення функції, але з анотаціями типів.
Але тепер уявіть, що ви знову посеред процесу створення функції, але з підказками типів.
В цей же момент, ви спробуєте викликати автозаповнення з допомогою `Ctrl+Space` і побачите:
У той самий момент ви спробуєте викликати автозаповнення за допомогою `Ctrl+Space` і побачите:
<img src="/img/python-types/image02.png">
Разом з цим, ви можете прокручувати, переглядати опції, допоки ви не знайдете одну, що звучить схоже:
Разом з цим ви можете прокручувати, переглядаючи опції, допоки не знайдете ту, що «щось вам підказує»:
<img src="/img/python-types/image03.png">
## Більше мотивації
## Більше мотивації { #more-motivation }
Перевірте цю функцію, вона вже має анотацію типу:
{* ../../docs_src/python_types/tutorial003.py hl[1] *}
Перевірте цю функцію, вона вже має підказки типів:
{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *}
Оскільки редактор знає типи змінних, ви не тільки отримаєте автозаповнення, ви також отримаєте перевірку помилок:
<img src="/img/python-types/image04.png">
Тепер ви знаєте, щоб виправити це, вам потрібно перетворити `age` у строку з допомогою `str(age)`:
Тепер ви знаєте, щоб виправити це, вам потрібно перетворити `age` у рядок за допомогою `str(age)`:
{* ../../docs_src/python_types/tutorial004.py hl[2] *}
{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *}
## Оголошення типів { #declaring-types }
## Оголошення типів
Щойно ви побачили основне місце для оголошення анотацій типу. Як параметри функції.
Щойно ви побачили основне місце для оголошення підказок типів. Як параметри функції.
Це також основне місце, де ви б їх використовували у **FastAPI**.
### Прості типи
### Прості типи { #simple-types }
Ви можете оголошувати усі стандартні типи у Python, не тільки `str`.
@@ -138,78 +133,51 @@ John Doe
* `bool`
* `bytes`
{* ../../docs_src/python_types/tutorial005.py hl[1] *}
{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *}
### Generic-типи з параметрами типів
### Generic-типи з параметрами типів { #generic-types-with-type-parameters }
Існують деякі структури даних, які можуть містити інші значення, наприклад `dict`, `list`, `set` та `tuple`. І внутрішні значення також можуть мати свій тип.
Ці типи, які мають внутрішні типи, називаються "**generic**" типами. І оголосити їх можна навіть із внутрішніми типами.
Ці типи, які мають внутрішні типи, називаються «**generic**» типами. І оголосити їх можна навіть із внутрішніми типами.
Щоб оголосити ці типи та внутрішні типи, ви можете використовувати стандартний модуль Python `typing`. Він існує спеціально для підтримки анотацій типів.
Щоб оголосити ці типи та внутрішні типи, ви можете використовувати стандартний модуль Python `typing`. Він існує спеціально для підтримки цих підказок типів.
#### Новіші версії Python
#### Новіші версії Python { #newer-versions-of-python }
Синтаксис із використанням `typing` **сумісний** з усіма версіями, від Python 3.6 до останніх, включаючи Python 3.9, Python 3.10 тощо.
У міру розвитку Python **новіші версії** мають покращену підтримку анотацій типів і в багатьох випадках вам навіть не потрібно буде імпортувати та використовувати модуль `typing` для оголошення анотацій типу.
У міру розвитку Python **новіші версії** мають покращену підтримку цих анотацій типів і в багатьох випадках вам навіть не потрібно буде імпортувати та використовувати модуль `typing` для оголошення анотацій типів.
Якщо ви можете вибрати новішу версію Python для свого проекту, ви зможете скористатися цією додатковою простотою. Дивіться кілька прикладів нижче.
Якщо ви можете вибрати новішу версію Python для свого проекту, ви зможете скористатися цією додатковою простотою.
#### List (список)
У всій документації є приклади, сумісні з кожною версією Python (коли є різниця).
Наприклад, «**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 { #list }
Наприклад, давайте визначимо змінну, яка буде `list` із `str`.
//// tab | Python 3.8 і вище
Оголосіть змінну з тим самим синтаксисом двокрапки (`:`).
З модуля `typing`, імпортуємо `List` (з великої літери `L`):
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial006.py!}
```
Оголосимо змінну з тим самим синтаксисом двокрапки (`:`).
Як тип вкажемо `List`, який ви імпортували з `typing`.
Як тип вкажіть `list`.
Оскільки список є типом, який містить деякі внутрішні типи, ви поміщаєте їх у квадратні дужки:
```Python hl_lines="4"
{!> ../../docs_src/python_types/tutorial006.py!}
```
{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *}
////
/// info | Інформація
//// tab | Python 3.9 і вище
Ці внутрішні типи в квадратних дужках називаються «параметрами типу».
Оголосимо змінну з тим самим синтаксисом двокрапки (`:`).
Як тип вкажемо `list`.
Оскільки список є типом, який містить деякі внутрішні типи, ви поміщаєте їх у квадратні дужки:
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial006_py39.py!}
```
////
/// info
Ці внутрішні типи в квадратних дужках називаються "параметрами типу".
У цьому випадку, `str` це параметр типу переданий у `List` (або `list` у Python 3.9 і вище).
У цьому випадку `str` — це параметр типу, переданий у `list`.
///
Це означає: "змінна `items` це `list`, і кожен з елементів у цьому списку - `str`".
/// tip
Якщо ви використовуєте Python 3.9 і вище, вам не потрібно імпортувати `List` з `typing`, ви можете використовувати натомість тип `list`.
///
Це означає: «змінна `items` це `list`, і кожен з елементів у цьому списку `str`».
Зробивши це, ваш редактор може надати підтримку навіть під час обробки елементів зі списку:
@@ -221,78 +189,42 @@ John Doe
І все ж редактор знає, що це `str`, і надає підтримку для цього.
#### Tuple and Set (кортеж та набір)
#### Tuple and Set { #tuple-and-set }
Ви повинні зробити те ж саме, щоб оголосити `tuple` і `set`:
//// tab | Python 3.8 і вище
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial007.py!}
```
////
//// tab | Python 3.9 і вище
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial007_py39.py!}
```
////
{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *}
Це означає:
* Змінна `items_t` це `tuple` з 3 елементами, `int`, ще `int`, та `str`.
* Змінна `items_s` це `set`, і кожен його елемент типу `bytes`.
* Змінна `items_t` це `tuple` з 3 елементами: `int`, ще `int`, та `str`.
* Змінна `items_s` це `set`, і кожен його елемент має тип `bytes`.
#### Dict (словник)
#### Dict { #dict }
Щоб оголосити `dict`, вам потрібно передати 2 параметри типу, розділені комами.
Перший параметр типу для ключа у `dict`.
Перший параметр типу для ключів у `dict`.
Другий параметр типу для значення у `dict`:
Другий параметр типу для значень у `dict`:
//// tab | Python 3.8 і вище
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial008.py!}
```
////
//// tab | Python 3.9 і вище
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial008_py39.py!}
```
////
{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *}
Це означає:
* Змінна `prices` це `dict`:
* Ключі цього `dict` типу `str` (наприклад, назва кожного елементу).
* Значення цього `dict` типу `float` (наприклад, ціна кожного елементу).
* Змінна `prices` це `dict`:
* Ключі цього `dict` мають тип `str` (скажімо, назва кожного елементу).
* Значення цього `dict` мають тип `float` (скажімо, ціна кожного елементу).
#### Union (об'єднання)
#### Union { #union }
Ви можете оголосити, що змінна може бути будь-яким із **кількох типів**, наприклад, `int` або `str`.
Ви можете оголосити, що змінна може бути будь-яким із **кількох типів**, наприклад `int` або `str`.
У Python 3.6 і вище (включаючи Python 3.10) ви можете використовувати тип `Union` з `typing` і вставляти в квадратні дужки можливі типи, які можна прийняти.
У Python 3.10 також є **альтернативний синтаксис**, у якому ви можете розділити можливі типи за допомогою <abbr title='також називають «побітовим "або" оператором», але це значення тут не актуальне'>вертикальної смуги (`|`)</abbr>.
У Python 3.10 також є **новий синтаксис**, у якому ви можете розділити можливі типи за допомогою <abbr title='також називають «побітовим "або" оператором», але це значення тут не актуальне'>вертикальної смуги (`|`)</abbr>.
//// tab | Python 3.8 і вище
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial008b.py!}
```
////
//// tab | Python 3.10 і вище
//// tab | Python 3.10+
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial008b_py310.py!}
@@ -300,16 +232,24 @@ John Doe
////
//// tab | Python 3.9+
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial008b_py39.py!}
```
////
В обох випадках це означає, що `item` може бути `int` або `str`.
#### Possibly `None` (Optional)
#### Можливо `None` { #possibly-none }
Ви можете оголосити, що значення може мати тип, наприклад `str`, але також може бути `None`.
У Python 3.6 і вище (включаючи Python 3.10) ви можете оголосити його, імпортувавши та використовуючи `Optional` з модуля `typing`.
```Python hl_lines="1 4"
{!../../docs_src/python_types/tutorial009.py!}
{!../../docs_src/python_types/tutorial009_py39.py!}
```
Використання `Optional[str]` замість просто `str` дозволить редактору допомогти вам виявити помилки, коли ви могли б вважати, що значенням завжди є `str`, хоча насправді воно також може бути `None`.
@@ -318,23 +258,7 @@ John Doe
Це також означає, що в Python 3.10 ви можете використовувати `Something | None`:
//// tab | Python 3.8 і вище
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial009.py!}
```
////
//// tab | Python 3.8 і вище - альтернатива
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial009b.py!}
```
////
//// tab | Python 3.10 і вище
//// tab | Python 3.10+
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial009_py310.py!}
@@ -342,32 +266,90 @@ John Doe
////
#### Generic типи
//// tab | Python 3.9+
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial009_py39.py!}
```
////
//// tab | Python 3.9+ alternative
```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 types** or **Generics**, наприклад:
//// tab | Python 3.8 і вище
//// tab | Python 3.10+
* `List`
* `Tuple`
* `Set`
* `Dict`
* `Union`
* `Optional`
* ...та інші.
////
//// tab | Python 3.9 і вище
Ви можете використовувати ті самі вбудовані типи, як generic (з квадратними дужками та типами всередині):
Ви можете використовувати ті самі вбудовані типи як generic (з квадратними дужками та типами всередині):
* `list`
* `tuple`
* `set`
* `dict`
І те саме, що й у Python 3.8, із модуля `typing`:
І так само, як і в попередніх версіях Python, з модуля `typing`:
* `Union`
* `Optional`
* ...та інші.
У Python 3.10 як альтернативу використанню generic `Union` та `Optional` ви можете використовувати <abbr title='також називають «побітовим "або" оператором», але це значення тут не актуальне'>вертикальну смугу (`|`)</abbr> для оголошення об’єднань типів — це значно краще й простіше.
////
//// tab | Python 3.9+
Ви можете використовувати ті самі вбудовані типи як generic (з квадратними дужками та типами всередині):
* `list`
* `tuple`
* `set`
* `dict`
І generic з модуля `typing`:
* `Union`
* `Optional`
@@ -375,46 +357,29 @@ John Doe
////
//// tab | Python 3.10 і вище
Ви можете використовувати ті самі вбудовані типи, як generic (з квадратними дужками та типами всередині):
* `list`
* `tuple`
* `set`
* `dict`
І те саме, що й у Python 3.8, із модуля `typing`:
* `Union`
* `Optional` (так само як у Python 3.8)
* ...та інші.
У Python 3.10, як альтернатива використанню `Union` та `Optional`, ви можете використовувати <abbr title='також називають «побітовим "або" оператором», але це значення тут не актуальне'>вертикальну смугу (`|`)</abbr> щоб оголосити об'єднання типів.
////
### Класи як типи
### Класи як типи { #classes-as-types }
Ви також можете оголосити клас як тип змінної.
Скажімо, у вас є клас `Person` з імʼям:
{* ../../docs_src/python_types/tutorial010.py hl[1:3] *}
{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *}
Потім ви можете оголосити змінну типу `Person`:
{* ../../docs_src/python_types/tutorial010.py hl[6] *}
{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *}
І знову ж таки, ви отримуєте всю підтримку редактора:
<img src="/img/python-types/image06.png">
## Pydantic моделі
Зверніть увагу, що це означає: «`one_person` — це **екземпляр** класу `Person`».
<a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> це бібліотека Python для валідації даних.
Це не означає: «`one_person` — це **клас** з назвою `Person.
## Pydantic моделі { #pydantic-models }
<a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> — це бібліотека Python для валідації даних.
Ви оголошуєте «форму» даних як класи з атрибутами.
@@ -424,33 +389,11 @@ John Doe
І ви отримуєте всю підтримку редактора з цим отриманим об’єктом.
Приклад з документації Pydantic:
Приклад з офіційної документації Pydantic:
//// tab | Python 3.8 і вище
{* ../../docs_src/python_types/tutorial011_py310.py *}
```Python
{!> ../../docs_src/python_types/tutorial011.py!}
```
////
//// tab | Python 3.9 і вище
```Python
{!> ../../docs_src/python_types/tutorial011_py39.py!}
```
////
//// tab | Python 3.10 і вище
```Python
{!> ../../docs_src/python_types/tutorial011_py310.py!}
```
////
/// info
/// info | Інформація
Щоб дізнатись більше про <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic, перегляньте його документацію</a>.
@@ -460,11 +403,43 @@ John Doe
Ви побачите набагато більше цього всього на практиці в [Tutorial - User Guide](tutorial/index.md){.internal-link target=_blank}.
## Анотації типів у **FastAPI**
/// tip | Порада
**FastAPI** використовує ці підказки для виконання кількох речей.
Pydantic має спеціальну поведінку, коли ви використовуєте `Optional` або `Union[Something, None]` без значення за замовчуванням; детальніше про це можна прочитати в документації Pydantic про <a href="https://docs.pydantic.dev/2.3/usage/models/#required-fields" class="external-link" target="_blank">Required Optional fields</a>.
З **FastAPI** ви оголошуєте параметри з підказками типу, і отримуєте:
///
## Підказки типів з анотаціями метаданих { #type-hints-with-metadata-annotations }
У Python також є можливість додавати **додаткові <abbr title="Дані про дані, у цьому випадку — інформація про тип, наприклад опис.">метадані</abbr>** до цих підказок типів за допомогою `Annotated`.
Починаючи з Python 3.9, `Annotated` є частиною стандартної бібліотеки, тож ви можете імпортувати його з `typing`.
{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *}
Сам Python нічого не робить із цим `Annotated`. А для редакторів та інших інструментів тип усе ще є `str`.
Але ви можете використати це місце в `Annotated`, щоб надати **FastAPI** додаткові метадані про те, як ви хочете, щоб ваш застосунок поводився.
Важливо пам’ятати, що **перший *параметр типу***, який ви передаєте в `Annotated`, — це **фактичний тип**. Решта — це лише метадані для інших інструментів.
Наразі вам просто потрібно знати, що `Annotated` існує і що це стандартний Python. 😎
Пізніше ви побачите, наскільки **потужним** це може бути.
/// tip | Порада
Той факт, що це **стандартний Python**, означає, що ви й надалі отримуватимете **найкращий можливий досвід розробки** у вашому редакторі, з інструментами, які ви використовуєте для аналізу та рефакторингу коду тощо. ✨
А також те, що ваш код буде дуже сумісним із багатьма іншими інструментами та бібліотеками Python. 🚀
///
## Анотації типів у **FastAPI** { #type-hints-in-fastapi }
**FastAPI** використовує ці підказки типів для виконання кількох речей.
З **FastAPI** ви оголошуєте параметри з підказками типів, і отримуєте:
* **Підтримку редактора**.
* **Перевірку типів**.
@@ -473,17 +448,17 @@ John Doe
* **Визначення вимог**: з параметрів шляху запиту, параметрів запиту, заголовків, тіл, залежностей тощо.
* **Перетворення даних**: із запиту в необхідний тип.
* **Перевірка даних**: що надходять від кожного запиту:
* **Перевірки даних**: що надходять від кожного запиту:
* Генерування **автоматичних помилок**, що повертаються клієнту, коли дані недійсні.
* **Документування** API за допомогою OpenAPI:
* який потім використовується для автоматичної інтерактивної документації користувальницьких інтерфейсів.
Все це може здатися абстрактним. Не хвилюйтеся. Ви побачите все це в дії в [Туторіал - Посібник користувача](tutorial/index.md){.internal-link target=_blank}.
Все це може здатися абстрактним. Не хвилюйтеся. Ви побачите все це в дії в [Tutorial - User Guide](tutorial/index.md){.internal-link target=_blank}.
Важливо те, що за допомогою стандартних типів Python в одному місці (замість того, щоб додавати більше класів, декораторів тощо), **FastAPI** зробить багато роботи за вас.
/// info
/// info | Інформація
Якщо ви вже пройшли весь навчальний посібник і повернулися, щоб дізнатися більше про типи, ось хороший ресурс <a href="https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html" class="external-link" target="_blank">"шпаргалка" від `mypy`</a>.
Якщо ви вже пройшли весь туторіал і повернулися, щоб дізнатися більше про типи, ось хороший ресурс: <a href="https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html" class="external-link" target="_blank">«шпаргалка» від `mypy`</a>.
///

View File

@@ -1,28 +1,27 @@
# Фонові задачі
# Фонові задачі { #background-tasks }
Ви можете створювати фонові задачі, які будуть виконуватися *після* повернення відповіді.
Це корисно для операцій, які потрібно виконати після обробки запиту, але клієнту не обов’язково чекати завершення цієї операції перед отриманням відповіді.
Приклади використання:
Це включає, наприклад:
* Надсилання email-сповіщень після виконання певної дії:
* Підключення до поштового сервера та надсилання листа може займати кілька секунд. Ви можете відразу повернути відповідь, а email відправити у фоні.
* Підключення до поштового сервера та надсилання листа може займати кілька секунд. Ви можете відразу повернути відповідь, а email-сповіщення надіслати у фоні.
* Обробка даних:
* Наприклад, якщо отримано файл, який потрібно обробити довготривалим процесом, можна повернути відповідь "Accepted" ("Прийнято", HTTP 202) і виконати обробку файлу у фоні.
* Наприклад, якщо ви отримали файл, який потрібно обробити довготривалим процесом, можна повернути відповідь «Accepted» (HTTP 202) і виконати обробку файлу у фоні.
## Використання `BackgroundTasks`
## Використання `BackgroundTasks` { #using-backgroundtasks }
Спочатку імпортуйте `BackgroundTasks` і додайте його як параметр у Вашу *функцію операції шляху* (path operation function) до `BackgroundTasks`:
Спочатку імпортуйте `BackgroundTasks` і оголосіть параметр у вашій *функції операції шляху* з анотацією типу `BackgroundTasks`:
{* ../../docs_src/background_tasks/tutorial001.py hl[1,13] *}
{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *}
**FastAPI** автоматично створить об'єкт `BackgroundTasks` і передасть його у цей параметр.
**FastAPI** створить для вас обєкт типу `BackgroundTasks` і передасть його як цей параметр.
## Створення функції задачі { #create-a-task-function }
## Створення функції задачі
Створіть функцію, яка буде виконувати фонову задачу.
Створіть функцію, яка буде виконуватися як фонова задача.
Це звичайна функція, яка може отримувати параметри.
@@ -32,54 +31,54 @@
І оскільки операція запису не використовує `async` та `await`, ми визначаємо функцію як звичайну `def`:
{* ../../docs_src/background_tasks/tutorial001.py hl[6:9] *}
{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *}
## Додавання фонової задачі
## Додавання фонової задачі { #add-the-background-task }
Усередині Вашої *функції обробки шляху*, передайте функцію задачі в об'єкт *background tasks*, використовуючи метод `.add_task()`:
Усередині вашої *функції операції шляху*, передайте функцію задачі в об'єкт *background tasks*, використовуючи метод `.add_task()`:
{* ../../docs_src/background_tasks/tutorial001.py hl[14] *}
{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *}
`.add_task()` приймає аргументи:
* Функція задача, яка буде виконуватися у фоновому режимі (`write_notification`). Зверніть увагу, що передається обʼєкт без дужок.
* Будь-яка послідовність аргументів, які потрібно передати у функцію завдання у відповідному порядку (`email`).
* Будь-які іменовані аргументи, які потрібно передати у функцію задачу (`message="some notification"`).
* Функцію задачі, яка буде виконуватися у фоновому режимі (`write_notification`).
* Будь-яку послідовність аргументів, які потрібно передати у функцію задачі у відповідному порядку (`email`).
* Будь-які іменовані аргументи, які потрібно передати у функцію задачі (`message="some notification"`).
## Впровадження залежностей
## Впровадження залежностей { #dependency-injection }
Використання `BackgroundTasks` також працює з системою впровадження залежностей. Ви можете оголосити параметр типу `BackgroundTasks` на різних рівнях: у *функції операції шляху*, у залежності (dependable), у під залежності тощо.
Використання `BackgroundTasks` також працює з системою впровадження залежностей. Ви можете оголосити параметр типу `BackgroundTasks` на різних рівнях: у *функції операції шляху*, у залежності (dependable), у підзалежності тощо.
**FastAPI** знає, як діяти в кожному випадку і як повторно використовувати один і той самий об'єкт, щоб усі фонові задачі були об’єднані та виконувалися у фоновому режимі після завершення основного запиту.
**FastAPI** знає, як діяти в кожному випадку і як повторно використовувати один і той самий об'єкт, щоб усі фонові задачі були об’єднані та виконувалися у фоновому режимі після завершення основного запиту:
{* ../../docs_src/background_tasks/tutorial002_an_py310.py hl[13,15,22,25] *}
У цьому прикладі повідомлення будуть записані у файл `log.txt` *після* того, як відповідь буде надіслана.
Якщо у запиті був переданий query-параметр, він буде записаний у лог у фоновій задачі.
Якщо у запиті був переданий query, він буде записаний у лог у фоновій задачі.
А потім інша фонова задача, яка створюється у *функції операції шляху*, запише повідомлення з використанням path параметра `email`.
А потім інша фонова задача, згенерована у *функції операції шляху*, запише повідомлення з використанням path параметра `email`.
## Технічні деталі
## Технічні деталі { #technical-details }
Клас `BackgroundTasks` походить безпосередньо з <a href="https://www.starlette.dev/background/" class="external-link" target="_blank">`starlette.background`</a>.
Він імпортується безпосередньо у FastAPI, щоб Ви могли використовувати його з `fastapi` і випадково не імпортували `BackgroundTask` (без s в кінці) з `starlette.background`.
Він імпортується/включається безпосередньо у FastAPI, щоб ви могли імпортувати його з `fastapi` і випадково не імпортували альтернативний `BackgroundTask` (без `s` в кінці) з `starlette.background`.
Якщо використовувати лише `BackgroundTasks` (а не `BackgroundTask`), то його можна передавати як параметр у *функції операції шляху*, і **FastAPI** подбає про все інше, так само як і про використання об'єкта `Request`.
Також можна використовувати `BackgroundTask` окремо в FastAPI, але для цього Вам доведеться створити об'єкт у коді та повернути Starlette `Response`, включаючи його.
Також можна використовувати `BackgroundTask` окремо в FastAPI, але для цього вам доведеться створити об'єкт у коді та повернути Starlette `Response`, включаючи його.
Детальніше можна почитати в <a href="https://www.starlette.dev/background/" class="external-link" target="_blank">офіційній документації Starlette про фонові задачі </a>.
Детальніше можна почитати в <a href="https://www.starlette.dev/background/" class="external-link" target="_blank">офіційній документації Starlette про Background Tasks</a>.
## Застереження
## Застереження { #caveat }
Якщо Вам потрібно виконувати складні фонові обчислення, і при цьому нема потреби запускати їх у тому ж процесі (наприклад, не потрібно спільного доступу до пам’яті чи змінних), можливо, варто скористатися більш потужними інструментами, такими як <a href="https://docs.celeryq.dev" class="external-link" target="_blank">Celery</a>.
Якщо вам потрібно виконувати складні фонові обчислення, і при цьому нема потреби запускати їх у тому ж процесі (наприклад, не потрібно спільного доступу до пам’яті чи змінних), можливо, варто скористатися більш потужними інструментами, такими як <a href="https://docs.celeryq.dev" class="external-link" target="_blank">Celery</a>.
Такі інструменти зазвичай потребують складнішої конфігурації та менеджера черги повідомлень/завдань, наприклад, RabbitMQ або Redis. Однак вони дозволяють виконувати фонові задачі в кількох процесах і навіть на кількох серверах.
Такі інструменти зазвичай потребують складнішої конфігурації та менеджера черги повідомлень/завдань, наприклад, RabbitMQ або Redis. Однак вони дозволяють виконувати фонові задачі в кількох процесах і особливо — на кількох серверах.
Якщо ж Вам потрібно отримати доступ до змінних і об’єктів із тієї ж **FastAPI** - програми або виконувати невеликі фонові завдання (наприклад, надсилати сповіщення електронною поштою), достатньо просто використовувати `BackgroundTasks`.
Якщо ж вам потрібно отримати доступ до змінних і об’єктів із тієї ж **FastAPI**-програми або виконувати невеликі фонові завдання (наприклад, надсилати email-сповіщення), достатньо просто використовувати `BackgroundTasks`.
## Підсумок
## Підсумок { #recap }
Імпортуйте та використовуйте `BackgroundTasks` як параметр у *функціях операції шляху* та залежностях, щоб додавати фонові задачі.
Імпортуйте та використовуйте `BackgroundTasks` як параметри у *функціях операції шляху* та залежностях, щоб додавати фонові задачі.

View File

@@ -1,60 +1,61 @@
# Тіло - Поля
# Тіло Поля { #body-fields }
Так само як ви можете визначати додаткову валідацію та метадані у параметрах *функції обробки шляху* за допомогою `Query`, `Path` та `Body`, ви можете визначати валідацію та метадані всередині моделей Pydantic за допомогою `Field` від Pydantic.
Так само як ви можете оголошувати додаткову валідацію та метадані в параметрах *функції операції шляху* за допомогою `Query`, `Path` та `Body`, ви можете оголошувати валідацію та метадані всередині моделей Pydantic, використовуючи `Field` від Pydantic.
## Імпорт `Field`
## Імпорт `Field` { #import-field }
Спочатку вам потрібно імпортувати це:
{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[4] *}
/// warning
Зверніть увагу, що `Field` імпортується прямо з `pydantic`, а не з `fastapi`, як всі інші (`Query`, `Path`, `Body` тощо).
/// warning | Попередження
Зверніть увагу, що `Field` імпортується безпосередньо з `pydantic`, а не з `fastapi`, як усе інше (`Query`, `Path`, `Body` тощо).
///
## Оголошення атрибутів моделі
## Оголошення атрибутів моделі { #declare-model-attributes }
Ви можете використовувати `Field` з атрибутами моделі:
Потім ви можете використовувати `Field` з атрибутами моделі:
{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[11:14] *}
`Field` працює так само, як `Query`, `Path` і `Body`, у нього такі самі параметри тощо.
`Field` працює так само, як `Query`, `Path` і `Body`, має ті самі параметри тощо.
/// note | Технічні деталі
Насправді, `Query`, `Path` та інші, що ви побачите далі, створюють об'єкти підкласів загального класу `Param`, котрий сам є підкласом класу `FieldInfo` з Pydantic.
Насправді `Query`, `Path` та інші, які ви побачите далі, створюють об'єкти підкласів спільного класу `Param`, який сам є підкласом класу `FieldInfo` з Pydantic.
І `Field` від Pydantic також повертає екземпляр `FieldInfo`.
`Body` також безпосередньо повертає об'єкти підкласу `FieldInfo`. І є інші підкласи, які ви побачите пізніше, що є підкласами класу Body.
`Body` також безпосередньо повертає об'єкти підкласу `FieldInfo`. І є інші, які ви побачите пізніше, що є підкласами класу `Body`.
Пам'ятайте, що коли ви імпортуєте 'Query', 'Path' та інше з 'fastapi', вони фактично є функціями, які повертають спеціальні класи.
Пам'ятайте, що коли ви імпортуєте `Query`, `Path` та інші з `fastapi`, це фактично функції, які повертають спеціальні класи.
///
/// tip
/// tip | Порада
Зверніть увагу, що кожен атрибут моделі із типом, значенням за замовчуванням та `Field` має ту саму структуру, що й параметр *функції обробки шляху*, з `Field` замість `Path`, `Query` і `Body`.
Зверніть увагу, що кожен атрибут моделі з типом, значенням за замовчуванням і `Field` має ту саму структуру, що й параметр *функції операції шляху*, з `Field` замість `Path`, `Query` і `Body`.
///
## Додавання додаткової інформації
## Додавання додаткової інформації { #add-extra-information }
Ви можете визначити додаткову інформацію у `Field`, `Query`, `Body` тощо. І вона буде включена у згенеровану JSON схему.
Ви можете оголошувати додаткову інформацію в `Field`, `Query`, `Body` тощо. І вона буде включена до згенерованої JSON Schema.
Ви дізнаєтеся більше про додавання додаткової інформації пізніше у документації, коли вивчатимете визначення прикладів.
Ви дізнаєтеся більше про додавання додаткової інформації пізніше в документації, коли вивчатимете, як оголошувати приклади.
/// warning
/// warning | Попередження
Додаткові ключі, передані в `Field`, також будуть присутні у згенерованій схемі OpenAPI для вашого додатка.
Оскільки ці ключі не обов'язково можуть бути частиною специфікації OpenAPI, деякі інструменти OpenAPI, наприклад, [OpenAPI валідатор](https://validator.swagger.io/), можуть не працювати з вашою згенерованою схемою.
Додаткові ключі, передані в `Field`, також будуть присутні в отриманій схемі OpenAPI для вашого застосунку.
Оскільки ці ключі не обов'язково є частиною специфікації OpenAPI, деякі інструменти OpenAPI, наприклад [валідатор OpenAPI](https://validator.swagger.io/), можуть не працювати з вашою згенерованою схемою.
///
## Підсумок
## Підсумок { #recap }
Ви можете використовувати `Field` з Pydantic для визначення додаткових перевірок та метаданих для атрибутів моделі.
Ви можете використовувати `Field` від Pydantic, щоб оголошувати додаткову валідацію та метадані для атрибутів моделі.
Ви також можете використовувати додаткові іменовані аргументи для передачі додаткових метаданих JSON схеми.
Ви також можете використовувати додаткові keyword arguments, щоб передавати додаткові метадані JSON Schema.

View File

@@ -1,24 +1,24 @@
# Тіло запиту - Декілька параметрів
# Тіло - Декілька параметрів { #body-multiple-parameters }
Тепер, коли ми розглянули використання `Path` та `Query`, розгляньмо більш просунуті способи оголошення тіла запиту в **FastAPI**.
Тепер, коли ми побачили, як використовувати `Path` і `Query`, розгляньмо більш просунуті варіанти оголошення тіла запиту.
## Змішування `Path`, `Query` та параметрів тіла запиту
## Змішування `Path`, `Query` та параметрів тіла { #mix-path-query-and-body-parameters }
По-перше, звісно, Ви можете вільно змішувати оголошення параметрів `Path`, `Query` та тіла запиту, і **FastAPI** правильно їх обробить.
По-перше, звісно, ви можете вільно змішувати оголошення параметрів `Path`, `Query` та тіла запиту, і **FastAPI** знатиме, що робити.
Також Ви можете оголосити параметри тіла як необов’язкові, встановивши для них значення за замовчуванням `None`:
Також ви можете оголошувати параметри тіла як необов’язкові, встановивши для них значення за замовчуванням `None`:
{* ../../docs_src/body_multiple_params/tutorial001_an_py310.py hl[18:20] *}
/// note | Примітка
Зверніть увагу, що в цьому випадку параметр `item`, який береться з тіла запиту, є необов'язковим, оскільки має значення за замовчуванням `None`.
Зверніть увагу, що в цьому випадку параметр `item`, який береться з тіла, є необов'язковим. Оскільки має значення за замовчуванням `None`.
///
## Декілька параметрів тіла запиту
## Декілька параметрів тіла { #multiple-body-parameters }
У попередньому прикладі *операція шляху* очікувала JSON з атрибутами `Item`, наприклад:
У попередньому прикладі *операції шляху* очікували б JSON-тіло з атрибутами `Item`, наприклад:
```JSON
{
@@ -28,13 +28,15 @@
"tax": 3.2
}
```
Але Ви також можете оголосити декілька параметрів тіла, наприклад `item` та `user`:
Але ви також можете оголосити декілька параметрів тіла, наприклад `item` та `user`:
{* ../../docs_src/body_multiple_params/tutorial002_py310.py hl[20] *}
У цьому випадку **FastAPI** розпізнає, що є кілька параметрів тіла (два параметри є моделями Pydantic).
Тому він використає назви параметрів як ключі (назви полів) у тілі запиту, очікуючи:
У цьому випадку **FastAPI** помітить, що у функції є більше ніж один параметр тіла (є два параметри, які є моделями Pydantic).
Тож він використає назви параметрів як ключі (назви полів) у тілі та очікуватиме тіло такого вигляду:
```JSON
{
@@ -53,27 +55,28 @@
/// note | Примітка
Зверніть увагу, що хоча `item` оголошено, так само як і раніше, тепер він очікується в тілі під ключем `item`.
Зверніть увагу, що хоча `item` оголошено так само, як і раніше, тепер він очікується всередині тіла з ключем `item`.
///
**FastAPI** автоматично конвертує дані із запиту таким чином, щоб параметр `item` отримав свій вміст, і те ж саме стосується `user`.
**FastAPI** виконає автоматичне перетворення із запиту, щоб параметр `item` отримав свій конкретний вміст, і те ж саме для `user`.
Він виконає валідацію складених даних і задокументує їх відповідним чином у схемі OpenAPI та в автоматичній документації.
Він виконає валідацію складених даних і задокументує це таким чином у схемі OpenAPI та в автоматичній документації.
## Одиничні значення в тілі запиту
## Одиничні значення в тілі { #singular-values-in-body }
Так само як є `Query` і `Path` для визначення додаткових даних для параметрів запиту та шляху, **FastAPI** надає еквівалентний `Body`.
Наприклад, розширюючи попередню модель, Ви можете вирішити додати ще один ключ `importance` в те ж саме тіло запиту разом із `item` і `user`.
Наприклад, розширивши попередню модель, ви можете вирішити додати ще один ключ `importance` у те саме тіло, окрім `item` і `user`.
Якщо Ви оголосите його як є, то, оскільки це одиничне значення, **FastAPI** припускатиме, що це параметр запиту (query parameter).
Якщо оголосити його як є, оскільки це одиничне значення, **FastAPI** припустить, що це параметр запиту.
Але Ви можете вказати **FastAPI** обробляти його як інший ключ тіла (body key), використовуючи `Body`:
Але ви можете вказати **FastAPI** обробляти його як інший ключ тіла, використовуючи `Body`:
{* ../../docs_src/body_multiple_params/tutorial003_an_py310.py hl[23] *}
У цьому випадку **FastAPI** очікуватиме тіло запиту у такому вигляді:
У цьому випадку **FastAPI** очікуватиме тіло такого вигляду:
```JSON
{
@@ -90,19 +93,20 @@
"importance": 5
}
```
Знову ж таки, **FastAPI** конвертуватиме типи даних, перевірятиме їх, створюватиме документацію тощо.
## Декілька body та query параметрів
Знову ж таки, він перетворюватиме типи даних, перевірятиме, документуватиме тощо.
Звісно, Ви можете оголошувати додаткові query параметри запиту, коли це необхідно, на додаток до будь-яких параметрів тіла запиту.
## Декілька параметрів тіла та query { #multiple-body-params-and-query }
Оскільки за замовчуванням окремі значення інтерпретуються як параметри запиту, Вам не потрібно явно додавати `Query`, можна просто використати:
Звісно, ви також можете оголошувати додаткові query параметри щоразу, коли це потрібно, додатково до будь-яких параметрів тіла.
Оскільки за замовчуванням одиничні значення інтерпретуються як параметри запиту, вам не потрібно явно додавати `Query`, ви можете просто зробити:
```Python
q: Union[str, None] = None
```
Або в Python 3.10 та вище:
Або в Python 3.10 і вище:
```Python
q: str | None = None
@@ -115,17 +119,17 @@ q: str | None = None
/// info | Інформація
`Body` також має ті самі додаткові параметри валідації та метаданих, що й `Query`, `Path` та інші, які Ви побачите пізніше.
`Body` також має всі ті самі додаткові параметри валідації та метаданих, що й `Query`, `Path` та інші, які ви побачите пізніше.
///
## Вкладений поодинокий параметр тіла запиту
## Вбудувати один параметр тіла { #embed-a-single-body-parameter }
Припустимо, у вас є лише один параметр тіла запиту `item` з моделі Pydantic `Item`.
Скажімо, у вас є лише один параметр тіла `item` з моделі Pydantic `Item`.
За замовчуванням **FastAPI** очікуватиме, що тіло запиту міститиме вміст безпосередньо.
За замовчуванням **FastAPI** очікуватиме його тіло безпосередньо.
Але якщо Ви хочете, щоб він очікував JSON з ключем `item`, а всередині — вміст моделі (так, як це відбувається при оголошенні додаткових параметрів тіла), Ви можете використати спеціальний параметр `Body``embed`:
Але якщо ви хочете, щоб він очікував JSON з ключем `item`, а всередині нього — вміст моделі, як це відбувається, коли ви оголошуєте додаткові параметри тіла, ви можете використати спеціальний параметр `Body``embed`:
```Python
item: Item = Body(embed=True)
@@ -135,7 +139,8 @@ item: Item = Body(embed=True)
{* ../../docs_src/body_multiple_params/tutorial005_an_py310.py hl[17] *}
У цьому випадку **FastAPI** очікуватиме тіло запиту такого вигляду:
У цьому випадку **FastAPI** очікуватиме тіло такого вигляду:
```JSON hl_lines="2"
{
@@ -159,12 +164,12 @@ item: Item = Body(embed=True)
}
```
## Підсумок
## Підсумок { #recap }
Ви можете додавати кілька параметрів тіла до Вашої *функції операції шляху* (*path operation function*), навіть якщо запит може мати лише одне тіло.
Ви можете додавати кілька параметрів тіла до вашої *функції операції шляху*, навіть якщо запит може мати лише одне тіло.
Але **FastAPI** обробить це, надасть Вам потрібні дані у функції, перевірить їх та задокументує коректну схему в *операції шляху*.
Але **FastAPI** обробить це, надасть вам правильні дані у функції та перевірить і задокументує правильну схему в *операції шляху*.
Також Ви можете оголошувати окремі значення, які будуть отримані як частина тіла запиту.
Також ви можете оголошувати одиничні значення, щоб отримувати їх як частину тіла.
Крім того, Ви можете вказати **FastAPI** вбудовувати тіло в ключ, навіть якщо оголошено лише один параметр.
І ви можете вказати **FastAPI** вбудовувати тіло в ключ, навіть коли оголошено лише один параметр.

View File

@@ -1,8 +1,8 @@
# Тіло запиту - Вкладені моделі
# Тіло - Вкладені моделі { #body-nested-models }
З **FastAPI** Ви можете визначати, перевіряти, документувати та використовувати моделі, які можуть бути вкладені на будь-яку глибину (завдяки Pydantic).
З **FastAPI** ви можете визначати, перевіряти, документувати та використовувати моделі, які можуть бути вкладені на будь-яку глибину (завдяки Pydantic).
## Поля списку
## Поля списку { #list-fields }
Ви можете визначити атрибут як підтип. Наприклад, Python-список (`list`):
@@ -10,47 +10,28 @@
Це зробить `tags` списком, хоча не визначається тип елементів списку.
## Поля списку з параметром типу
## Поля списку з параметром типу { #list-fields-with-type-parameter }
Але Python має специфічний спосіб оголошення списків з внутрішніми типами або "параметрами типу":
### Імпортуємо `List` з модуля typing
Але Python має специфічний спосіб оголошення списків з внутрішніми типами або «параметрами типу»:
У Python 3.9 і вище можна використовувати стандартний `list` для оголошення таких типів, як ми побачимо нижче. 💡
### Оголошення `list` з параметром типу { #declare-a-list-with-a-type-parameter }
Але в Python версії до 3.9 (від 3.6 і вище) спочатку потрібно імпортувати `List` з модуля стандартної бібліотеки Python `typing`:
{* ../../docs_src/body_nested_models/tutorial002.py hl[1] *}
### Оголошення `list` з параметром типу
Щоб оголосити типи з параметрами типу (внутрішніми типами), такими як `list`, `dict`, `tuple`:
* Якщо Ви використовуєте версію Python до 3.9, імпортуйте їх відповідну версію з модуля `typing`.
* Передайте внутрішні типи як "параметри типу", використовуючи квадратні дужки: `[` and `]`.
У Python 3.9 це буде виглядати так:
Щоб оголосити типи з параметрами типу (внутрішніми типами), такими як `list`, `dict`, `tuple`,
передайте внутрішні тип(и) як «параметри типу», використовуючи квадратні дужки: `[` and `]`
```Python
my_list: list[str]
```
У версіях Python до 3.9 це виглядає так:
```Python
from typing import List
my_list: List[str]
```
Це стандартний синтаксис Python для оголошення типів.
Використовуйте той самий стандартний синтаксис для атрибутів моделей з внутрішніми типами.
Отже, у нашому прикладі, ми можемо зробити `tags` саме "списком рядків":
Отже, у нашому прикладі, ми можемо зробити `tags` саме «списком рядків»:
{* ../../docs_src/body_nested_models/tutorial002_py310.py hl[12] *}
## Типи множин
## Типи множин { #set-types }
Але потім ми подумали, що теги не повинні повторюватися, вони, ймовірно, повинні бути унікальними рядками.
@@ -60,29 +41,29 @@ my_list: List[str]
{* ../../docs_src/body_nested_models/tutorial003_py310.py hl[12] *}
Навіть якщо Ви отримаєте запит з дубльованими даними, він буде перетворений у множину унікальних елементів.
Навіть якщо ви отримаєте запит з дубльованими даними, він буде перетворений у множину унікальних елементів.
І коли Ви будете виводити ці дані, навіть якщо джерело містить дублікати, вони будуть виведені як множина унікальних елементів.
І коли ви будете виводити ці дані, навіть якщо джерело містить дублікати, вони будуть виведені як множина унікальних елементів.
І це буде анотовано/документовано відповідно.
## Вкладені моделі
## Вкладені моделі { #nested-models }
Кожен атрибут моделі Pydantic має тип.
Але цей тип сам може бути іншою моделлю Pydantic.
Отже, Ви можете оголосити глибоко вкладені JSON "об'єкти" з конкретними іменами атрибутів, типами та перевірками.
Отже, ви можете оголосити глибоко вкладені JSON «об'єкти» з конкретними іменами атрибутів, типами та перевірками.
Усе це, вкладене без обмежень.
### Визначення підмоделі
### Визначення підмоделі { #define-a-submodel }
Наприклад, ми можемо визначити модель `Image`:
{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[7:9] *}
### Використання підмоделі як типу
### Використання підмоделі як типу { #use-the-submodel-as-a-type }
А потім ми можемо використовувати її як тип атрибута:
@@ -104,16 +85,16 @@ my_list: List[str]
}
```
Завдяки такій декларації у **FastAPI** Ви отримуєте:
Завдяки такій декларації у **FastAPI** ви отримуєте:
* Підтримку в редакторі (автозавершення тощо), навіть для вкладених моделей
* Конвертацію даних
* Валідацію даних
* Автоматичну документацію
## Спеціальні типи та валідація
## Спеціальні типи та валідація { #special-types-and-validation }
Окрім звичайних типів, таких як `str`, `int`, `float`, та ін. Ви можете використовувати складніші типи, які наслідують `str`.
Окрім звичайних типів, таких як `str`, `int`, `float`, та ін. ви можете використовувати складніші типи, які наслідують `str`.
Щоб побачити всі доступні варіанти, ознайомтеся з оглядом <a href="https://docs.pydantic.dev/latest/concepts/types/" class="external-link" target="_blank">типів у Pydantic</a>. Деякі приклади будуть у наступних розділах.
@@ -123,9 +104,9 @@ my_list: List[str]
Рядок буде перевірено як дійсну URL-адресу і задокументовано в JSON Schema / OpenAPI як URL.
## Атрибути зі списками підмоделей
## Атрибути зі списками підмоделей { #attributes-with-lists-of-submodels }
У Pydantic Ви можете використовувати моделі як підтипи для `list`, `set` тощо:
У Pydantic ви можете використовувати моделі як підтипи для `list`, `set` тощо:
{* ../../docs_src/body_nested_models/tutorial006_py310.py hl[18] *}
@@ -161,7 +142,7 @@ my_list: List[str]
///
## Глибоко вкладені моделі
## Глибоко вкладені моделі { #deeply-nested-models }
Ви можете визначати вкладені моделі довільної глибини:
@@ -173,14 +154,9 @@ my_list: List[str]
///
## Тіла запитів, що складаються зі списків
## Тіла запитів, що складаються зі списків { #bodies-of-pure-lists }
Якщо верхній рівень JSON тіла, яке Ви очікуєте, є JSON `масивом` (у Python — `list`), Ви можете оголосити тип у параметрі функції, як і в моделях Pydantic:
```Python
images: List[Image]
```
або в Python 3.9 і вище:
Якщо верхній рівень JSON тіла, яке ви очікуєте, є JSON `масивом` (у Python — `list`), ви можете оголосити тип у параметрі функції, як і в моделях Pydantic:
```Python
images: list[Image]
@@ -190,7 +166,7 @@ images: list[Image]
{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *}
## Підтримка в редакторі всюди
## Підтримка в редакторі всюди { #editor-support-everywhere }
Ви отримаєте підтримку в редакторі всюди.
@@ -200,23 +176,23 @@ images: list[Image]
Ви не змогли б отримати таку підтримку в редакторі, якби працювали напряму зі `dict`, а не з моделями Pydantic.
Але Вам не потрібно турбуватися про це: вхідні dict'и автоматично конвертуються, а вихідні дані автоматично перетворюються в JSON.
Але вам не потрібно турбуватися про це: вхідні dict'и автоматично конвертуються, а вихідні дані автоматично перетворюються в JSON.
## Тіла з довільними `dict`
## Тіла з довільними `dict` { #bodies-of-arbitrary-dicts }
Ви також можете оголосити тіло як `dict` з ключами одного типу та значеннями іншого типу.
Це корисно, якщо Ви не знаєте наперед, які імена полів будуть дійсними (як у випадку з моделями Pydantic).
Це корисно, якщо ви не знаєте наперед, які імена полів будуть дійсними (як у випадку з моделями Pydantic).
Це буде корисно, якщо Ви хочете приймати ключі, які заздалегідь невідомі.
Це буде корисно, якщо ви хочете приймати ключі, які заздалегідь невідомі.
---
Це також зручно, якщо Ви хочете мати ключі іншого типу (наприклад, `int`).
Це також зручно, якщо ви хочете мати ключі іншого типу (наприклад, `int`).
Ось що ми розглянемо далі.
У цьому випадку Ви можете приймати будь-який `dict`, якщо його ключі — це `int`, а значення — `float`:
У цьому випадку ви можете приймати будь-який `dict`, якщо його ключі — це `int`, а значення — `float`:
{* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *}
@@ -228,18 +204,18 @@ images: list[Image]
Це означає, що навіть якщо клієнти вашого API надсилатимуть ключі у вигляді рядків, якщо вони містять цілі числа, Pydantic конвертує їх і проведе валідацію.
Тобто `dict`, який Ви отримаєте як `weights`, матиме ключі типу `int` та значення типу `float`.
Тобто `dict`, який ви отримаєте як `weights`, матиме ключі типу `int` та значення типу `float`.
///
## Підсумок
## Підсумок { #recap }
З **FastAPI** Ви маєте максимальну гнучкість завдяки моделям Pydantic, зберігаючи при цьому код простим, коротким та елегантним.
З **FastAPI** ви маєте максимальну гнучкість завдяки моделям Pydantic, зберігаючи при цьому код простим, коротким та елегантним.
А також отримуєте всі переваги:
* Підтримка в редакторі (автодоповнення всюди!)
* Конвертація даних (парсинг/сериалізація)
* Валідація даних
* Валідацію даних
* Документація схем
* Автоматичне створення документації

View File

@@ -1,8 +1,8 @@
# Тіло Оновлення
# Тіло Оновлення
## Оновлення з використанням `PUT`
## Оновлення із заміною за допомогою `PUT`
Щоб оновити елемент, Ви можете використати <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT" class="external-link" target="_blank">HTTP `PUT`</a> операцію.
Щоб оновити елемент, ви можете використати <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT" class="external-link" target="_blank">HTTP `PUT`</a> операцію.
Ви можете використати `jsonable_encoder`, щоб перетворити вхідні дані на такі, які можна зберігати як JSON (наприклад, у NoSQL базі даних). Наприклад, перетворюючи `datetime` у `str`.
@@ -10,7 +10,7 @@
`PUT` використовується для отримання даних, які мають замінити чинні дані.
### Попередження про заміну
### Попередження про заміну { #warning-about-replacing }
Це означає, що якщо Ви хочете оновити елемент `bar`, використовуючи `PUT` з тілом:
@@ -34,53 +34,37 @@
/// note | Примітка
`PATCH` менш відомий і рідше використовується, ніж `PUT`.
`PATCH` менш поширений і менш відомий, ніж `PUT`.
І багато команд використовують лише `PUT`, навіть для часткових оновлень.
Ви **вільні** використовувати їх так, як хочете, **FastAPI** не накладає обмежень.
Ви **вільні** використовувати їх так, як хочете, **FastAPI** не накладає жодних обмежень.
Але цей посібник показує Вам більш-менш як їх задумано використовувати.
Але цей посібник показує вам, більш-менш, як їх задумано використовувати.
///
### Використання параметра `exclude_unset` у Pydantic
### Використання параметра `exclude_unset` у Pydantic { #using-pydantics-exclude-unset-parameter }
Якщо Ви хочете отримати часткові оновлення, дуже зручно використовувати параметр `exclude_unset` у методі `.model_dump()` моделі Pydantic.
Якщо Ви хочете отримувати часткові оновлення, дуже корисно використовувати параметр `exclude_unset` у `.model_dump()` моделі Pydantic.
Наприклад: `item.model_dump(exclude_unset=True)`.
/// info | Інформація
Це згенерує `dict` лише з тими даними, які були встановлені під час створення моделі `item`, виключаючи значення за замовчуванням.
У Pydantic v1 цей метод називався `.dict()`, він був застарілий (але все ще підтримується) у Pydantic v2, і був перейменований у `.model_dump()`.
Приклади тут використовують `.dict()` для сумісності з Pydantic v1, але Вам слід використовувати `.model_dump()`, якщо можете використовувати Pydantic v2.
///
Це створить `dict` лише з тими даними, які були явно встановлені під час створення моделі `item`, виключаючи значення за замовчуванням.
Тоді Ви можете використовувати це, щоб створити `dict` лише з даними, які були встановлені (надіслані у запиті), пропускаючи значення за замовчуванням:
Тоді Ви можете використовувати це, щоб згенерувати `dict` лише з даними, які були встановлені (надіслані у запиті), пропускаючи значення за замовчуванням:
{* ../../docs_src/body_updates/tutorial002_py310.py hl[32] *}
### Використання параметра `update` у Pydantic
### Використання параметра `update` у Pydantic { #using-pydantics-update-parameter }
Тепер Ви можете створити копію наявної моделі за допомогою `.model_copy()`, і передати параметр `update` з `dict` , який містить дані для оновлення.
/// info | Інформація
У Pydantic v1 метод називався `.copy()`, він був застарілий (але все ще підтримується) у Pydantic v2, і був перейменований у `.model_copy()`.
Приклади тут використовують `.copy()` для сумісності з Pydantic v1, але якщо Ви можете використовувати Pydantic v2 — Вам слід використовувати `.model_copy()` замість цього.
///
Тепер Ви можете створити копію наявної моделі за допомогою `.model_copy()`, і передати параметр `update` з `dict`, який містить дані для оновлення.
Наприклад: `stored_item_model.model_copy(update=update_data)`:
{* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *}
### Підсумок часткових оновлень
### Підсумок часткових оновлень { #partial-updates-recap }
У підсумку, щоб застосувати часткові оновлення, Ви:
@@ -101,7 +85,7 @@
Насправді Ви можете використовувати цю саму техніку і з операцією HTTP `PUT`.
Але приклад тут використовує `PATCH`, тому що він був створений саме для таких випадків.
Але приклад тут використовує `PATCH`, тому що він був створений для таких випадків.
///
@@ -109,7 +93,7 @@
Зверніть увагу, що модель запиту все ще проходить валідацію.
Тож, якщо Ви хочете отримувати часткові оновлення, які можуть не містити жодного атрибута, Вам потрібно мати модель, де всі атрибути позначені як необов’язкові (зі значеннями за замовчуванням або `None`).
Тож, якщо Ви хочете отримувати часткові оновлення, які можуть пропускати всі атрибути, Вам потрібно мати модель, де всі атрибути позначені як необов’язкові (зі значеннями за замовчуванням або `None`).
Щоб розрізняти моделі з усіма необов’язковими значеннями для **оновлення** і моделі з обов’язковими значеннями для **створення**, Ви можете скористатись ідеями, описаними у [Додаткові моделі](extra-models.md){.internal-link target=_blank}.

View File

@@ -1,14 +1,14 @@
# Тіло запиту
# Тіло запиту { #request-body }
Коли вам потрібно надіслати дані з клієнта (скажімо, браузера) до вашого API, ви надсилаєте їх як **тіло запиту**.
Тіло **запиту** — це дані, надіслані клієнтом до вашого API. Тіло **відповіді** — це дані, які ваш API надсилає клієнту.
Ваш API майже завжди має надсилати тіло **відповіді**. Але клієнтам не обов’язково потрібно постійно надсилати тіла **запитів**.
Ваш API майже завжди має надсилати тіло **відповіді**. Але клієнтам не обов’язково потрібно постійно надсилати тіла **запитів** — інколи вони лише запитують шлях, можливо з деякими параметрами запиту, але не надсилають тіло.
Щоб оголосити тіло **запиту**, ви використовуєте <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> моделі з усією їх потужністю та перевагами.
/// info
/// info | Інформація
Щоб надіслати дані, ви повинні використовувати один із: `POST` (більш поширений), `PUT`, `DELETE` або `PATCH`.
@@ -18,21 +18,22 @@
///
## Імпортуйте `BaseModel` від Pydantic
## Імпортуйте `BaseModel` від Pydantic { #import-pydantics-basemodel }
Спочатку вам потрібно імпортувати `BaseModel` з `pydantic`:
{* ../../docs_src/body/tutorial001.py hl[4] *}
{* ../../docs_src/body/tutorial001_py310.py hl[2] *}
## Створіть свою модель даних
## Створіть свою модель даних { #create-your-data-model }
Потім ви оголошуєте свою модель даних як клас, який успадковується від `BaseModel`.
Використовуйте стандартні типи Python для всіх атрибутів:
{* ../../docs_src/body/tutorial001.py hl[7:11] *}
{* ../../docs_src/body/tutorial001_py310.py hl[5:9] *}
Так само, як і при оголошенні параметрів запиту, коли атрибут моделі має значення за замовчуванням, він не є обов’язковим. В іншому випадку це потрібно. Використовуйте `None`, щоб зробити його необов'язковим.
Так само, як і при оголошенні параметрів запиту, коли атрибут моделі має значення за замовчуванням, він не є обов’язковим. В іншому випадку це потрібно. Використовуйте `None`, щоб зробити його просто необов'язковим.
Наприклад, ця модель вище оголошує JSON "`об'єкт`" (або Python `dict`), як:
@@ -54,15 +55,15 @@
}
```
## Оголоси її як параметр
## Оголосіть її як параметр { #declare-it-as-a-parameter }
Щоб додати модель даних до вашої *операції шляху*, оголосіть її так само, як ви оголосили параметри шляху та запиту:
{* ../../docs_src/body/tutorial001.py hl[18] *}
{* ../../docs_src/body/tutorial001_py310.py hl[16] *}
...і вкажіть її тип як модель, яку ви створили, `Item`.
## Результати
## Результати { #results }
Лише з цим оголошенням типу Python **FastAPI** буде:
@@ -73,9 +74,9 @@
* Надавати отримані дані у параметрі `item`.
* Оскільки ви оголосили його у функції як тип `Item`, ви також матимете всю підтримку редактора (автозаповнення, тощо) для всіх атрибутів та їх типів.
* Генерувати <a href="https://json-schema.org" class="external-link" target="_blank">JSON Schema</a> визначення для вашої моделі, ви також можете використовувати їх де завгодно, якщо це має сенс для вашого проекту.
* Ці схеми будуть частиною згенерованої схеми OpenAPI і використовуватимуться автоматичною документацією інтерфейсу користувача.
* Ці схеми будуть частиною згенерованої схеми OpenAPI і використовуватимуться автоматичною документацією <abbr title="User Interfaces Інтерфейси користувача">UIs</abbr>.
## Автоматична документація
## Автоматична документація { #automatic-docs }
Схеми JSON ваших моделей будуть частиною вашої схеми, згенерованої OpenAPI, і будуть показані в інтерактивній API документації:
@@ -85,7 +86,7 @@
<img src="/img/tutorial/body/image02.png">
## Підтримка редактора
## Підтримка редактора { #editor-support }
У вашому редакторі, всередині вашої функції, ви будете отримувати підказки типу та завершення скрізь (це б не сталося, якби ви отримали `dict` замість моделі Pydantic):
@@ -107,7 +108,7 @@
<img src="/img/tutorial/body/image05.png">
/// tip
/// tip | Порада
Якщо ви використовуєте <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a> як ваш редактор, ви можете використати <a href="https://github.com/koxudaxi/pydantic-pycharm-plugin/" class="external-link" target="_blank">Pydantic PyCharm Plugin</a>.
@@ -121,42 +122,45 @@
///
## Використовуйте модель
## Використовуйте модель { #use-the-model }
Усередині функції ви можете отримати прямий доступ до всіх атрибутів об’єкта моделі:
{* ../../docs_src/body/tutorial002.py hl[21] *}
{* ../../docs_src/body/tutorial002_py310.py *}
## Тіло запиту + параметри шляху
## Тіло запиту + параметри шляху { #request-body-path-parameters }
Ви можете одночасно оголошувати параметри шляху та тіло запиту.
**FastAPI** розпізнає, що параметри функції, які відповідають параметрам шляху, мають бути **взяті з шляху**, а параметри функції, які оголошуються як моделі Pydantic, **взяті з тіла запиту**.
{* ../../docs_src/body/tutorial003.py hl[17:18] *}
{* ../../docs_src/body/tutorial003_py310.py hl[15:16] *}
## Тіло запиту + шлях + параметри запиту
## Тіло запиту + шлях + параметри запиту { #request-body-path-query-parameters }
Ви також можете оголосити параметри **тіло**, **шлях** і **запит** одночасно.
**FastAPI** розпізнає кожен з них і візьме дані з потрібного місця.
{* ../../docs_src/body/tutorial004.py hl[18] *}
{* ../../docs_src/body/tutorial004_py310.py hl[16] *}
Параметри функції будуть розпізнаватися наступним чином:
* Якщо параметр також оголошено в **шляху**, він використовуватиметься як параметр шляху.
* Якщо параметр має **сингулярний тип** (наприклад, `int`, `float`, `str`, `bool` тощо), він буде інтерпретуватися як параметр **запиту**.
* Якщо параметр оголошується як тип **Pydantic моделі**, він інтерпретується як **тіло** запиту.
* Якщо параметр оголошується як тип **Pydantic моделі**, він інтерпретується як **тіло** **запиту**.
/// note
/// note | Примітка
FastAPI буде знати, що значення "q" не є обов'язковим через значення за замовчуванням "= None".
FastAPI буде знати, що значення `q` не є обов'язковим через значення за замовчуванням `= None`.
`Optional` у `Optional[str]` не використовується FastAPI, але дозволить вашому редактору надати вам кращу підтримку та виявляти помилки.
`str | None` (Python 3.10+) або `Union` у `Union[str, None]` (Python 3.9+) FastAPI не використовує, щоб визначити, що значення не є обов’язковим — він знатиме, що воно не є обов’язковим, тому що має значення за замовчуванням `= None`.
Але додавання анотацій типів дозволить вашому редактору надати вам кращу підтримку та виявляти помилки.
///
## Без Pydantic
## Без Pydantic { #without-pydantic }
Якщо ви не хочете використовувати моделі Pydantic, ви також можете використовувати параметри **Body**. Перегляньте документацію для [Тіло Кілька параметрів: сингулярні значення в тілі](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}.
Якщо ви не хочете використовувати моделі Pydantic, ви також можете використовувати параметри **Body**. Перегляньте документацію для [Body - Multiple Parameters: Singular values in body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}.

View File

@@ -1,32 +1,32 @@
# Моделі для Cookie-параметрів
# Моделі параметрів Cookie { #cookie-parameter-models }
Якщо у Вас є група **cookies** параметрів, які пов'язані між собою, Ви можете створити **Pydantic-модель**, щоб оголосити їх. 🍪
Якщо у Вас є група **cookies**, які пов'язані між собою, Ви можете створити **Pydantic-модель**, щоб оголосити їх. 🍪
Це дозволить Вам повторно **використовувати модель** у **різних місцях**, а також оголосити валідацію та метадані для всіх параметрів одночасно. 😎
/// note | Нотатки
/// note | Примітка
Це підтримується з версії FastAPI `0.115.0`. 🤓
Це підтримується з версії FastAPI `0.115.0`. 🤓
///
/// tip | Порада
Ця ж техніка застосовується до `Query`, `Cookie`, та `Header`. 😎
Ця ж техніка застосовується до `Query`, `Cookie` та `Header`. 😎
///
## Cookie з Pydantic-моделлю
## Cookie з Pydantic-моделлю { #cookies-with-a-pydantic-model }
Оголосіть **cookie-параметри**, які Вам потрібні, у **Pydantic-моделі**, а потім оголосіть параметр як `Cookie`:
Оголосіть **cookie**-параметри, які Вам потрібні, у **Pydantic-моделі**, а потім оголосіть параметр як `Cookie`:
{* ../../docs_src/cookie_param_models/tutorial001_an_py310.py hl[9:12,16] *}
**FastAPI** буде **витягувати** дані для **кожного поля** з **cookie** параметрів, отриманих у запиті, і передавати Вам Pydantic-модель, яку Ви визначили.
**FastAPI** буде **витягувати** дані для **кожного поля** з **cookies**, отриманих у запиті, і передавати Вам Pydantic-модель, яку Ви визначили.
## Перевірка у документації
## Перевірка у документації { #check-the-docs }
Ви можете побачити визначені cookie в інтерфейсі документації за адресою `/docs`:
Ви можете побачити визначені cookies в інтерфейсі документації за адресою `/docs`:
<div class="screenshot">
<img src="/img/tutorial/cookie-param-models/image01.png">
@@ -34,29 +34,29 @@
/// info | Інформація
Майте на увазі, що оскільки **браузери обробляють cookie** особливим чином і "за лаштунками", вони **не** дозволяють **JavaScript** легко з ними працювати.
Майте на увазі, що оскільки **браузери обробляють cookies** особливим чином і «за лаштунками», вони **не** дозволяють **JavaScript** легко з ними працювати.
Якщо Ви зайдете до **інтерфейсу документації API** за адресою `/docs`, Ви зможете побачити **документацію** для cookie у Ваших **операціях шляху**.
Якщо Ви зайдете до **інтерфейсу документації API** за адресою `/docs`, Ви зможете побачити **документацію** для cookies у Ваших *операціях шляху*.
Але навіть якщо Ви заповните дані й натиснете "Execute", оскільки інтерфейс документації працює з **JavaScript**, cookie не будуть відправлені, і Ви побачите **помилку**, ніби Ви не ввели жодних значень.
Але навіть якщо Ви заповните дані й натиснете "Execute", оскільки інтерфейс документації працює з **JavaScript**, cookies не будуть відправлені, і Ви побачите **помилку**, ніби Ви не ввели жодних значень.
///
## Заборона додаткових cookie
## Заборона додаткових cookie { #forbid-extra-cookies }
У деяких спеціальних випадках (ймовірно, не дуже поширених) Ви можете захотіти **обмежити** список cookie, які хочете отримувати.
У деяких спеціальних випадках (ймовірно, не дуже поширених) Ви можете захотіти **обмежити** cookies, які хочете отримувати.
Ваша API тепер має можливість контролювати власну <abbr title="Це жарт, якщо що. Це не має нічого спільного зі згодою на використання cookie, але це кумедно, що навіть API тепер може відхиляти бідні cookie. Ловіть печиво. 🍪">згоду на cookie</abbr>. 🤪🍪
Ваша API тепер має можливість контролювати власну <abbr title="This is a joke, just in case. It has nothing to do with cookie consents, but it's funny that even the API can now reject the poor cookies. Have a cookie. 🍪">згоду на cookie</abbr>. 🤪🍪
Ви можете використовувати налаштування моделі Pydantic, щоб `заборонити` будь-які `додаткові` поля:
Ви можете використовувати налаштування моделі Pydantic, щоб `forbid` будь-які `extra` поля:
{* ../../docs_src/cookie_param_models/tutorial002_an_py39.py hl[10] *}
{* ../../docs_src/cookie_param_models/tutorial002_an_py310.py hl[10] *}
Якщо клієнт спробує надіслати якісь **додаткові cookie**, він отримає відповідь з **помилкою**.
Якщо клієнт спробує надіслати якісь **додаткові cookies**, він отримає відповідь з **помилкою**.
Бідні банери cookie, які так старанно намагаються отримати Вашу згоду, щоб <abbr title="Це ще один жарт. Не звертайте уваги. Візьміть каву для свого печива. ☕">API її відхилила</abbr>. 🍪
Бідні банери cookie, які так старанно намагаються отримати Вашу згоду, щоб <abbr title="This is another joke. Don't pay attention to me. Have some coffee for your cookie. ☕">API її відхилила</abbr>. 🍪
Наприклад, якщо клієнт спробує надіслати cookie `santa_tracker` зі значенням `good-list-please`, він отримає відповідь з помилкою, яка повідомить, що <abbr title="Санта не схвалює відсутність cookie. 🎅 Гаразд, більше жартів не буде.">cookie `santa_tracker` не дозволено</abbr>:
Наприклад, якщо клієнт спробує надіслати cookie `santa_tracker` зі значенням `good-list-please`, він отримає відповідь з помилкою, яка повідомить, що `santa_tracker` <abbr title="Santa disapproves the lack of cookies. 🎅 Okay, no more cookie jokes.">cookie не дозволено</abbr>:
```json
{
@@ -71,6 +71,6 @@
}
```
## Підсумок
## Підсумок { #summary }
Ви можете використовувати **Pydantic-моделі** для оголошення <abbr title="Отримайте останнє печиво перед тим, як піти. 🍪">cookie</abbr> у FastAPI. 😎
Ви можете використовувати **Pydantic-моделі** для оголошення <abbr title="Have a last cookie before you go. 🍪">**cookies**</abbr> у **FastAPI**. 😎

View File

@@ -1,24 +1,25 @@
# Параметри Cookie
# Параметри Cookie { #cookie-parameters }
Ви можете визначити параметри Cookie таким же чином, як визначаються параметри `Query` і `Path`.
Ви можете визначати параметри Cookie таким же чином, як визначаються параметри `Query` і `Path`.
## Імпорт `Cookie`
## Імпорт `Cookie` { #import-cookie }
Спочатку імпортуйте `Cookie`:
{* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[3] *}
## Визначення параметрів `Cookie`
## Визначення параметрів `Cookie` { #declare-cookie-parameters }
Потім визначте параметри cookie, використовуючи таку ж конструкцію як для `Path` і `Query`.
Перше значення це значення за замовчуванням, ви можете також передати всі додаткові параметри валідації чи анотації:
Ви можете визначити значення за замовчуванням, а також усі додаткові параметри валідації чи анотації:
{* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[9] *}
/// note | Технічні Деталі
/// note | Технічні деталі
`Cookie` це "сестра" класів `Path` і `Query`. Вони також наслідуються від одного спільного класу `Param`.
`Cookie` це "сестра" класів `Path` і `Query`. Вони наслідуються від одного батьківського класу `Param`.
Але пам'ятайте, що коли ви імпортуєте `Query`, `Path`, `Cookie` та інше з `fastapi`, це фактично функції, що повертають спеціальні класи.
///
@@ -29,6 +30,16 @@
///
## Підсумки
/// info
Майте на увазі, що оскільки **браузери обробляють cookies** спеціальним чином і за лаштунками, вони **не** дозволяють **JavaScript** легко взаємодіяти з ними.
Якщо ви перейдете до **інтерфейсу документації API** за адресою `/docs`, ви зможете побачити **документацію** для cookies для ваших *операцій шляху*.
Але навіть якщо ви **заповните дані** і натиснете "Execute", оскільки інтерфейс документації працює з **JavaScript**, cookies не буде надіслано, і ви побачите повідомлення про **помилку**, ніби ви не ввели жодних значень.
///
## Підсумки { #recap }
Визначайте cookies за допомогою `Cookie`, використовуючи той же спільний шаблон, що і `Query` та `Path`.

View File

@@ -1,8 +1,8 @@
# CORS (Обмін ресурсами між різними джерелами)
# CORS (Обмін ресурсами між різними джерелами) { #cors-cross-origin-resource-sharing }
<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external-link" target="_blank">CORS або "Обмін ресурсами між різними джерелами"</a> є ситуація, коли фронтенд, що працює в браузері, містить JavaScript-код, який взаємодіє з бекендом, розташованим в іншому "джерелі" (origin).
<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external-link" target="_blank">CORS або "Cross-Origin Resource Sharing"</a> є ситуація, коли фронтенд, що працює в браузері, містить JavaScript-код, який взаємодіє з бекендом, розташованим в іншому "джерелі" (origin).
## Джерело (Origin)
## Джерело (Origin) { #origin }
Джерело визначається комбінацією протоколу (`http`, `https`), домену (`myapp.com`, `localhost`, `localhost.tiangolo.com`), порту (`80`, `443`, `8080`).
@@ -15,7 +15,7 @@
Навіть якщо вони всі містять `localhost`, вони мають різні протоколи або порти, що робить їх окремими "джерелами".
## Кроки
## Кроки { #steps }
Припустимо, що Ваш фронтенд працює в браузері на `http://localhost:8080`, а його JavaScript намагається відправити запит до бекенду, який працює на `http://localhost` (Оскільки ми не вказуємо порт, браузер за замовчуванням припускає порт `80`).
@@ -25,15 +25,15 @@
У цьому випадку список має містити `http://localhost:8080`, щоб фронтенд на порту `:8080` працював коректно.
## Символьне підставляння
## Символьне підставляння { #wildcards }
Можна також оголосити список як `"*"` ("символьне підставляння"), що означає дозвіл для всіх джерел.
Однак це дозволить лише певні типи комунікації, виключаючи все, що пов'язане з обліковими даними: Cookies, заголовки авторизації, такі як ті, що використовуються з Bearer токенами тощо.
Однак це дозволить лише певні типи комунікації, виключаючи все, що пов'язане з обліковими даними: Cookies, заголовки авторизації, такі як ті, що використовуються з Bearer Tokens, тощо.
Тому для коректної роботи краще явно вказувати дозволені джерела.
## Використання `CORSMiddleware`
## Використання `CORSMiddleware` { #use-corsmiddleware }
Ви можете налаштувати це у Вашому додатку **FastAPI** за допомогою `CORSMiddleware`.
@@ -44,41 +44,44 @@
Також можна вказати, чи дозволяє Ваш бекенд:
* Облікові дані (заголовки авторизації, сookies, тощо).
* Облікові дані (заголовки авторизації, Cookies, тощо).
* Конкретні HTTP-методи (`POST`, `PUT`) або всі за допомогою `"*"`
* Конкретні HTTP-заголовки або всі за допомогою `"*"`.
{* ../../docs_src/cors/tutorial001.py hl[2,6:11,13:19] *}
{* ../../docs_src/cors/tutorial001_py39.py hl[2,6:11,13:19] *}
Параметри за замовчуванням у `CORSMiddleware` є досить обмеженими, тому Вам потрібно явно вказати конкретні джерела, методи або заголовки, щоб браузери могли використовувати їх у контексті запитів між різними доменами.
Параметри за замовчуванням у реалізації `CORSMiddleware` є досить обмеженими, тому Вам потрібно явно увімкнути конкретні джерела, методи або заголовки, щоб браузерам було дозволено використовувати їх у міждоменному контексті.
Підтримуються такі аргументи:
* `allow_origins` - Список джерел, яким дозволено здійснювати міждоменні запити. Наприклад `['https://example.org', 'https://www.example.org']`. Ви можете використовувати ['*'], щоб дозволити всі джерела.
* `allow_origins` - Список джерел, яким дозволено здійснювати міждоменні запити. Наприклад `['https://example.org', 'https://www.example.org']`. Ви можете використовувати `['*']`, щоб дозволити будь-яке джерело.
* `allow_origin_regex` - Рядок регулярного виразу для відповідності джерелам, яким дозволено здійснювати міждоменні запити. Наприклад, `'https://.*\.example\.org'`.
* `allow_methods` - Список HTTP-методів, дозволених для міждоменних запитів. За замовчуванням `['GET']`. Ви можете використовувати `['*']`, щоб дозволити всі стандартні методи.
* `allow_headers` - Список HTTP-заголовків, які підтримуються для міждоменних запитів. За замовчуванням `[]`. Ви можете використовувати `['*']`, щоб дозволити всі заголовки. Заголовки `Accept`, `Accept-Language`, `Content-Language` і `Content-Type` завжди дозволені для <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests" class="external-link" rel="noopener" target="_blank">простих CORS-запитів</a>.
* `allow_credentials` - Визначає, чи підтримуються файли cookie для міждоменних запитів. За замовчуванням `False`. Також, якщо потрібно дозволити обмін обліковими даними (`allow_credentials = True`), параметр `allow_origins` не може бути встановлений як `['*']`, необхідно вказати конкретні джерела.
* `allow_headers` - Список HTTP-заголовків запиту, які підтримуються для міждоменних запитів. За замовчуванням `[]`. Ви можете використовувати `['*']`, щоб дозволити всі заголовки. Заголовки `Accept`, `Accept-Language`, `Content-Language` і `Content-Type` завжди дозволені для <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests" class="external-link" rel="noopener" target="_blank">простих CORS-запитів</a>.
* `allow_credentials` - Визначає, чи повинні підтримуватися cookies для міждоменних запитів. За замовчуванням `False`.
Жоден із параметрів `allow_origins`, `allow_methods` і `allow_headers` не можна встановлювати як `['*']`, якщо `allow_credentials` встановлено як `True`. Усі вони мають бути <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#credentialed_requests_and_wildcards" class="external-link" rel="noopener" target="_blank">явно вказані</a>.
* `expose_headers` - Вказує, які заголовки відповіді повинні бути доступні для браузера. За замовчуванням `[]`.
* `max_age` - Встановлює максимальний час (у секундах) для кешування CORS-відповідей у браузерах. За замовчуванням `600`.
Цей middleware обробляє два типи HTTP-запитів...
### Попередні CORS-запити (preflight requests)
### Попередні CORS-запити { #cors-preflight-requests }
Це будь-які `OPTIONS` - запити, що містять заголовки `Origin` та `Access-Control-Request-Method`.
У такому випадку middleware перехопить вхідний запит і відповість відповідними CORS-заголовками, повертаючи або `200`, або `400` для інформаційних цілей.
### Прості запити
### Прості запити { #simple-requests }
Будь-які запити із заголовком `Origin`. У цьому випадку middleware пропустить запит як звичайний, але додасть відповідні CORS-заголовки у відповідь.
## Додаткова інформація
## Додаткова інформація { #more-info }
Більше про <abbr title="Cross-Origin Resource Sharing">CORS</abbr> можна дізнатися в <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external-link" target="_blank">документації Mozilla</a>.
Більше про <abbr title="Cross-Origin Resource Sharing">CORS</abbr> можна дізнатися в <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external-link" target="_blank">документації Mozilla про CORS</a>.
/// note | Технічні деталі

View File

@@ -1,16 +1,16 @@
# Налагодження (Debugging)
# Налагодження { #debugging }
Ви можете під'єднати дебагер у Вашому редакторі коду, наприклад, у Visual Studio Code або PyCharm.
Ви можете під'єднати дебагер у вашому редакторі коду, наприклад, у Visual Studio Code або PyCharm.
## Виклик `uvicorn`
## Виклик `uvicorn` { #call-uvicorn }
У Вашому FastAPI-додатку імпортуйте та запустіть `uvicorn` безпосередньо:
У вашому FastAPI-додатку імпортуйте та запустіть `uvicorn` безпосередньо:
{* ../../docs_src/debugging/tutorial001.py hl[1,15] *}
{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *}
### Про `__name__ == "__main__"`
### Про `__name__ == "__main__"` { #about-name-main }
Головна мета використання `__name__ == "__main__"` — це забезпечення виконання певного коду тільки тоді, коли файл запускається безпосередньо:
Головна мета використання `__name__ == "__main__"` — це забезпечення виконання певного коду лише тоді, коли ваш файл запускається так:
<div class="termy">
@@ -20,17 +20,17 @@ $ python myapp.py
</div>
але не виконується при його імпорті в інший файл, наприклад:
але не виконується, коли інший файл імпортує його, наприклад:
```Python
from myapp import app
```
#### Детальніше
#### Детальніше { #more-details }
Припустимо, Ваш файл називається `myapp.py`.
Припустимо, ваш файл називається `myapp.py`.
Якщо Ви запустите його так:
Якщо ви запустите його так:
<div class="termy">
@@ -40,7 +40,7 @@ $ python myapp.py
</div>
тоді внутрішня змінна `__name__`, яка створюється автоматично Python, матиме значення `"__main__"`.
тоді внутрішня змінна `__name__` у вашому файлі, яка створюється автоматично Python, матиме значення рядка `"__main__"`.
Отже, цей блок коду:
@@ -52,17 +52,17 @@ $ python myapp.py
---
Це не станеться, якщо Ви імпортуєте цей модуль (файл).
Це не станеться, якщо ви імпортуєте цей модуль (файл).
Якщо у Вас є інший файл, наприклад `importer.py`, з наступним кодом:
Отже, якщо у вас є інший файл `importer.py` з:
```Python
from myapp import app
# Додатковий код
# Some more code
```
У цьому випадку автоматично створена змінна у файлі `myapp.py` не матиме значення змінної `__name__` як `"__main__"`.
у цьому випадку автоматично створена змінна `__name__` всередині `myapp.py` не матиме значення `"__main__"`.
Отже, рядок:
@@ -74,38 +74,39 @@ from myapp import app
/// info | Інформація
Більш детальну інформацію можна знайти в <a href="https://docs.python.org/3/library/__main__.html" class="external-link" target="_blank">офіційній документації Python</a>.
Для отримання додаткової інформації дивіться <a href="https://docs.python.org/3/library/__main__.html" class="external-link" target="_blank">офіційну документацію Python</a>.
///
## Запуск коду з вашим дебагером
## Запуск коду з вашим дебагером { #run-your-code-with-your-debugger }
Оскільки Ви запускаєте сервер Uvicorn безпосередньо з Вашого коду, Ви можете запустити вашу Python програму (ваш FastAPI додаток) безпосередньо з дебагера.
Оскільки ви запускаєте сервер Uvicorn безпосередньо з вашого коду, ви можете запустити вашу Python програму (ваш FastAPI-додаток) безпосередньо з дебагера.
---
Наприклад, у Visual Studio Code Ви можете:
Наприклад, у Visual Studio Code ви можете:
* Перейдіть на вкладку "Debug".
* Натисніть "Add configuration...".
* Виберіть "Python"
* Перейдіть на панель «Debug».
* «Add configuration...».
* Виберіть «Python»
* Запустіть дебагер з опцією "`Python: Current File (Integrated Terminal)`".
Це запустить сервер з Вашим **FastAPI** кодом, зупиниться на точках зупину тощо.
Після цього він запустить сервер з вашим кодом **FastAPI**, зупиниться на точках зупину тощо.
Ось як це може виглядати:
<img src="/img/tutorial/debugging/image01.png">
---
Якщо Ви використовуєте PyCharm, ви можете:
* Відкрити меню "Run".
* Вибрати опцію "Debug...".
Якщо ви використовуєте PyCharm, ви можете:
* Відкрити меню «Run».
* Вибрати опцію «Debug...».
* Потім з'явиться контекстне меню.
* Вибрати файл для налагодження (у цьому випадку, `main.py`).
Це запустить сервер з Вашим **FastAPI** кодом, зупиниться на точках зупину тощо.
Після цього він запустить сервер з вашим кодом **FastAPI**, зупиниться на точках зупину тощо.
Ось як це може виглядати:

View File

@@ -1,32 +1,32 @@
# JSON Compatible Encoder
# JSON-сумісний кодувальник { #json-compatible-encoder }
Існують випадки, коли вам може знадобитися перетворити тип даних (наприклад, модель Pydantic) в щось сумісне з JSON (наприклад, `dict`, `list`, і т. д.).
Існують випадки, коли вам може знадобитися перетворити тип даних (наприклад, модель Pydantic) на щось сумісне з JSON (наприклад, `dict`, `list` тощо).
Наприклад, якщо вам потрібно зберегти це в базі даних.
Для цього, **FastAPI** надає `jsonable_encoder()` функцію.
Для цього **FastAPI** надає функцію `jsonable_encoder()`.
## Використання `jsonable_encoder`
## Використання `jsonable_encoder` { #using-the-jsonable-encoder }
Давайте уявимо, що у вас є база даних `fake_db`, яка приймає лише дані, сумісні з JSON.
Наприклад, вона не приймає об'єкти типу `datetime`, оскільки вони не сумісні з JSON.
Отже, об'єкт типу `datetime` потрібно перетворити в рядок `str`, який містить дані в <a href="https://en.wikipedia.org/wiki/ISO_8601" class="external-link" target="_blank">ISO форматі</a>.
Отже, об'єкт типу `datetime` потрібно перетворити на `str`, який містить дані в <a href="https://en.wikipedia.org/wiki/ISO_8601" class="external-link" target="_blank">форматі ISO</a>.
Тим самим способом ця база даних не прийматиме об'єкт типу Pydantic model (об'єкт з атрибутами), а лише `dict`.
Так само ця база даних не прийматиме модель Pydantic (об'єкт з атрибутами), а лише `dict`.
Ви можете використовувати `jsonable_encoder` для цього.
Вона приймає об'єкт, такий як Pydantic model, і повертає його версію, сумісну з JSON:
Вона приймає об'єкт, такий як модель Pydantic, і повертає його версію, сумісну з JSON:
{* ../../docs_src/encoder/tutorial001_py310.py hl[4,21] *}
У цьому прикладі вона конвертує Pydantic model у `dict`, а `datetime` у `str`.
У цьому прикладі вона конвертує модель Pydantic у `dict`, а `datetime` у `str`.
Результат виклику цієї функції - це щось, що можна кодувати з використанням стандарту Python <a href="https://docs.python.org/3/library/json.html#json.dumps" class="external-link" target="_blank">`json.dumps()`</a>.
Результат виклику цієї функції це щось, що можна кодувати з використанням стандарту Python <a href="https://docs.python.org/3/library/json.html#json.dumps" class="external-link" target="_blank">`json.dumps()`</a>.
Вона не повертає велику строку `str`, яка містить дані у форматі JSON (як строка). Вона повертає стандартну структуру даних Python (наприклад `dict`) із значеннями та підзначеннями, які є сумісними з JSON.
Вона не повертає великий `str`, який містить дані у форматі JSON (як рядок). Вона повертає стандартну структуру даних Python (наприклад, `dict`) зі значеннями та підзначеннями, які є сумісними з JSON.
/// note | Примітка

View File

@@ -1,13 +1,13 @@
# Додаткові типи даних
# Додаткові типи даних { #extra-data-types }
До цього часу, ви використовували загальнопоширені типи даних, такі як:
До цього часу ви використовували загальнопоширені типи даних, такі як:
* `int`
* `float`
* `str`
* `bool`
Але можна також використовувати більш складні типи даних.
Але ви також можете використовувати більш складні типи даних.
І ви все ще матимете ті ж можливості, які були показані до цього:
@@ -17,30 +17,30 @@
* Валідація даних.
* Автоматична анотація та документація.
## Інші типи даних
## Інші типи даних { #other-data-types }
Ось додаткові типи даних для використання:
* `UUID`:
* Стандартний "Універсальний Унікальний Ідентифікатор", який часто використовується як ідентифікатор у багатьох базах даних та системах.
* Стандартний "Універсальний унікальний ідентифікатор", який часто використовується як ID у багатьох базах даних та системах.
* У запитах та відповідях буде представлений як `str`.
* `datetime.datetime`:
* Пайтонівський `datetime.datetime`.
* У запитах та відповідях буде представлений як `str` в форматі ISO 8601, як: `2008-09-15T15:53:00+05:00`.
* У запитах та відповідях буде представлений як `str` у форматі ISO 8601, як: `2008-09-15T15:53:00+05:00`.
* `datetime.date`:
* Пайтонівський `datetime.date`.
* У запитах та відповідях буде представлений як `str` в форматі ISO 8601, як: `2008-09-15`.
* У запитах та відповідях буде представлений як `str` у форматі ISO 8601, як: `2008-09-15`.
* `datetime.time`:
* Пайтонівський `datetime.time`.
* У запитах та відповідях буде представлений як `str` в форматі ISO 8601, як: `14:23:55.003`.
* У запитах та відповідях буде представлений як `str` у форматі ISO 8601, як: `14:23:55.003`.
* `datetime.timedelta`:
* Пайтонівський `datetime.timedelta`.
* У запитах та відповідях буде представлений як `float` загальної кількості секунд.
* Pydantic також дозволяє представляти це як "ISO 8601 time diff encoding", <a href="https://docs.pydantic.dev/latest/concepts/serialization/#json_encoders" class="external-link" target="_blank">більше інформації дивись у документації</a>.
* Pydantic також дозволяє представляти це як "ISO 8601 time diff encoding", <a href="https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers" class="external-link" target="_blank">дивіться документацію для отримання додаткової інформації</a>.
* `frozenset`:
* У запитах і відповідях це буде оброблено так само, як і `set`:
* У запитах список буде зчитано, дублікати будуть видалені та він буде перетворений на `set`.
* У відповідях, `set` буде перетворений на `list`.
* У запитах список буде зчитано, дублікати буде видалено, і його буде перетворено на `set`.
* У відповідях `set` буде перетворено на `list`.
* Згенерована схема буде вказувати, що значення `set` є унікальними (з використанням JSON Schema's `uniqueItems`).
* `bytes`:
* Стандартний Пайтонівський `bytes`.
@@ -49,11 +49,11 @@
* `Decimal`:
* Стандартний Пайтонівський `Decimal`.
* У запитах і відповідях це буде оброблено так само, як і `float`.
* Ви можете перевірити всі дійсні типи даних Pydantic тут: <a href="https://docs.pydantic.dev/latest/concepts/types/" class="external-link" target="_blank">типи даних Pydantic</a>.
* Ви можете перевірити всі дійсні типи даних Pydantic тут: <a href="https://docs.pydantic.dev/latest/usage/types/types/" class="external-link" target="_blank">типи даних Pydantic</a>.
## Приклад
## Приклад { #example }
Ось приклад *path operation* з параметрами, використовуючи деякі з вищезазначених типів.
Ось приклад *операції шляху* з параметрами, використовуючи деякі з вищезазначених типів.
{* ../../docs_src/extra_data_types/tutorial001_an_py310.py hl[1,3,12:16] *}

View File

@@ -1,126 +1,118 @@
# Перші кроки
# Перші кроки { #first-steps }
Найпростіший файл FastAPI може виглядати так:
{* ../../docs_src/first_steps/tutorial001.py *}
{* ../../docs_src/first_steps/tutorial001_py39.py *}
Скопіюйте це до файлу `main.py`.
Запустіть сервер:
Запустіть live-сервер:
<div class="termy">
```console
$ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:single">main.py</u>
<font color="#3465A4">INFO </font> Using path <font color="#3465A4">main.py</font>
<font color="#3465A4">INFO </font> Resolved absolute path <font color="#75507B">/home/user/code/awesomeapp/</font><font color="#AD7FA8">main.py</font>
<font color="#3465A4">INFO </font> Searching for package file structure from directories with <font color="#3465A4">__init__.py</font> files
<font color="#3465A4">INFO </font> Importing from <font color="#75507B">/home/user/code/</font><font color="#AD7FA8">awesomeapp</font>
$ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:solid">main.py</u>
╭─ <font color="#8AE234"><b>Python module file</b></font> ─╮
│ │
│ 🐍 main.py │
│ │
╰──────────────────────╯
<span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span> Starting development server 🚀
<font color="#3465A4">INFO </font> Importing module <font color="#4E9A06">main</font>
<font color="#3465A4">INFO </font> Found importable FastAPI app
Searching for package file structure from directories
with <font color="#3465A4">__init__.py</font> files
Importing from <font color="#75507B">/home/user/code/</font><font color="#AD7FA8">awesomeapp</font>
╭─ <font color="#8AE234"><b>Importable FastAPI app</b></font> ─╮
│ │
│ <span style="background-color:#272822"><font color="#FF4689">from</font></span><span style="background-color:#272822"><font color="#F8F8F2"> main </font></span><span style="background-color:#272822"><font color="#FF4689">import</font></span><span style="background-color:#272822"><font color="#F8F8F2"> app</font></span><span style="background-color:#272822"> </span> │
│ │
╰──────────────────────────╯
<span style="background-color:#007166"><font color="#D3D7CF"> module </font></span> 🐍 main.py
<font color="#3465A4">INFO </font> Using import string <font color="#8AE234"><b>main:app</b></font>
<span style="background-color:#007166"><font color="#D3D7CF"> code </font></span> Importing the FastAPI app object from the module with
the following code:
<span style="background-color:#C4A000"><font color="#2E3436">╭────────── FastAPI CLI - Development mode ───────────╮</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ Serving at: http://127.0.0.1:8000 │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ API docs: http://127.0.0.1:8000/docs │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ Running in development mode, for production use: │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ </font></span><span style="background-color:#C4A000"><font color="#555753"><b>fastapi run</b></font></span><span style="background-color:#C4A000"><font color="#2E3436"> │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">╰─────────────────────────────────────────────────────╯</font></span>
<u style="text-decoration-style:solid">from </u><u style="text-decoration-style:solid"><b>main</b></u><u style="text-decoration-style:solid"> import </u><u style="text-decoration-style:solid"><b>app</b></u>
<font color="#4E9A06">INFO</font>: Will watch for changes in these directories: [&apos;/home/user/code/awesomeapp&apos;]
<font color="#4E9A06">INFO</font>: Uvicorn running on <b>http://127.0.0.1:8000</b> (Press CTRL+C to quit)
<font color="#4E9A06">INFO</font>: Started reloader process [<font color="#34E2E2"><b>2265862</b></font>] using <font color="#34E2E2"><b>WatchFiles</b></font>
<font color="#4E9A06">INFO</font>: Started server process [<font color="#06989A">2265873</font>]
<font color="#4E9A06">INFO</font>: Waiting for application startup.
<font color="#4E9A06">INFO</font>: Application startup complete.
<span style="background-color:#007166"><font color="#D3D7CF"> app </font></span> Using import string: <font color="#3465A4">main:app</font>
<span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Server started at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font>
<span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Documentation at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000/docs</u></font>
<span style="background-color:#007166"><font color="#D3D7CF"> tip </font></span> Running in development mode, for production use:
<b>fastapi run</b>
Logs:
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Will watch for changes in these directories:
<b>[</b><font color="#4E9A06">&apos;/home/user/code/awesomeapp&apos;</font><b>]</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Uvicorn running on <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font> <b>(</b>Press CTRL+C
to quit<b>)</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started reloader process <b>[</b><font color="#34E2E2"><b>383138</b></font><b>]</b> using WatchFiles
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>383153</b></font><b>]</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
```
</div>
У консолі буде рядок приблизно такого змісту:
У виводі є рядок приблизно такого змісту:
```hl_lines="4"
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
Цей рядок показує URL, за яким додаток запускається на вашій локальній машині.
Цей рядок показує URL, за яким ваш застосунок обслуговується на вашій локальній машині.
### Перевірте
### Перевірте { #check-it }
Відкрийте браузер та введіть адресу <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>.
Ви побачите у відповідь таке повідомлення у форматі JSON:
Ви побачите JSON-відповідь:
```JSON
{"message": "Hello World"}
```
### Інтерактивна API документація
### Інтерактивна API документація { #interactive-api-docs }
Перейдемо сюди <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
Тепер перейдіть сюди <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
Ви побачите автоматичну інтерактивну API документацію (створену завдяки <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
Ви побачите автоматичну інтерактивну API документацію (надається <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### Альтернативна API документація
### Альтернативна API документація { #alternative-api-docs }
Тепер перейдемо сюди <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
А тепер перейдіть сюди <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
Ви побачите альтернативну автоматичну документацію (створену завдяки <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
Ви побачите альтернативну автоматичну документацію (надається <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
### OpenAPI
### OpenAPI { #openapi }
**FastAPI** генерує "схему" з усім вашим API, використовуючи стандарт **OpenAPI** для визначення API.
**FastAPI** генерує «схему» з усім вашим API, використовуючи стандарт **OpenAPI** для визначення API.
#### "Схема"
#### «Схема» { #schema }
"Схема" - це визначення або опис чогось. Це не код, який його реалізує, а просто абстрактний опис.
«Схема» — це визначення або опис чогось. Це не код, який його реалізує, а просто абстрактний опис.
#### API "схема"
#### API «схема» { #api-schema }
У цьому випадку, <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> є специфікацією, яка визначає, як описати схему вашого API.
Це визначення схеми включає шляхи (paths) вашого API, можливі параметри, які вони приймають тощо.
Це визначення схеми включає шляхи (paths) вашого API, можливі параметри, які вони приймають, тощо.
#### "Схема" даних
#### «Схема» даних { #data-schema }
Термін "схема" також може відноситися до структури даних, наприклад, JSON.
Термін «схема» також може відноситися до форми деяких даних, наприклад, вмісту JSON.
У цьому випадку це означає - атрибути JSON і типи даних, які вони мають тощо.
У цьому випадку це означає атрибути JSON і типи даних, які вони мають, тощо.
#### OpenAPI і JSON Schema
#### OpenAPI і JSON Schema { #openapi-and-json-schema }
OpenAPI описує схему для вашого API. І ця схема включає визначення (або "схеми") даних, що надсилаються та отримуються вашим API за допомогою **JSON Schema**, стандарту для схем даних JSON.
OpenAPI описує схему API для вашого API. І ця схема включає визначення (або «схеми») даних, що надсилаються та отримуються вашим API, за допомогою **JSON Schema**, стандарту для схем даних JSON.
#### Розглянемо `openapi.json`
#### Перевірте `openapi.json` { #check-the-openapi-json }
Якщо вас цікавить, як виглядає вихідна схема OpenAPI, то FastAPI автоматично генерує JSON-схему з усіма описами API.
Якщо вас цікавить, як виглядає «сирий» OpenAPI schema, FastAPI автоматично генерує JSON (schema) з описами всього вашого API.
Ознайомитися можна за посиланням: <a href="http://127.0.0.1:8000/openapi.json" class="external-link" target="_blank">http://127.0.0.1:8000/openapi.json</a>.
Ви можете побачити це напряму тут: <a href="http://127.0.0.1:8000/openapi.json" class="external-link" target="_blank">http://127.0.0.1:8000/openapi.json</a>.
Ви побачите приблизно такий JSON:
Ви побачите JSON, що починається приблизно так:
```JSON
{
@@ -143,42 +135,79 @@ OpenAPI описує схему для вашого API. І ця схема вк
...
```
#### Для чого потрібний OpenAPI
#### Для чого потрібний OpenAPI { #what-is-openapi-for }
Схема OpenAPI є основою для обох систем інтерактивної документації.
OpenAPI schema — це те, на чому працюють дві включені системи інтерактивної документації.
Існують десятки альтернативних інструментів, заснованих на OpenAPI. Ви можете легко додати будь-який з них до **FastAPI** додатку.
Також існують десятки альтернатив, і всі вони засновані на OpenAPI. Ви можете легко додати будь-яку з цих альтернатив до вашого застосунку, створеного з **FastAPI**.
Ви також можете використовувати OpenAPI для автоматичної генерації коду для клієнтів, які взаємодіють з API. Наприклад, для фронтенд-, мобільних або IoT-додатків
Ви також можете використовувати його для автоматичної генерації коду для клієнтів, які взаємодіють з вашим API. Наприклад, для фронтенд-, мобільних або IoT-застосунків.
## А тепер крок за кроком
### Розгорніть ваш застосунок (необовʼязково) { #deploy-your-app-optional }
### Крок 1: імпортуємо `FastAPI`
За бажанням ви можете розгорнути ваш FastAPI-застосунок у <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>, перейдіть і приєднайтеся до списку очікування, якщо ви цього ще не зробили. 🚀
{* ../../docs_src/first_steps/tutorial001.py hl[1] *}
Якщо у вас вже є обліковий запис **FastAPI Cloud** (ми запросили вас зі списку очікування 😉), ви можете розгорнути ваш застосунок однією командою.
`FastAPI` це клас у Python, який надає всю функціональність для API.
Перед розгортанням переконайтеся, що ви увійшли:
<div class="termy">
```console
$ fastapi login
You are logged in to FastAPI Cloud 🚀
```
</div>
Потім розгорніть ваш застосунок:
<div class="termy">
```console
$ fastapi deploy
Deploying to FastAPI Cloud...
✅ Deployment successful!
🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev
```
</div>
Ось і все! Тепер ви можете отримати доступ до вашого застосунку за цим URL. ✨
## Підібʼємо підсумки, крок за кроком { #recap-step-by-step }
### Крок 1: імпортуємо `FastAPI` { #step-1-import-fastapi }
{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *}
`FastAPI` — це клас у Python, який надає всю функціональність для вашого API.
/// note | Технічні деталі
`FastAPI` це клас, який успадковується безпосередньо від `Starlette`.
`FastAPI` це клас, який успадковується безпосередньо від `Starlette`.
Ви також можете використовувати всю функціональність <a href="https://www.starlette.dev/" class="external-link" target="_blank">Starlette</a> у `FastAPI`.
///
### Крок 2: створюємо екземпляр `FastAPI`
### Крок 2: створюємо «екземпляр» `FastAPI` { #step-2-create-a-fastapi-instance }
{* ../../docs_src/first_steps/tutorial001.py hl[3] *}
Змінна `app` є екземпляром класу `FastAPI`.
{* ../../docs_src/first_steps/tutorial001_py39.py hl[3] *}
Це буде головна точка для створення і взаємодії з API.
Тут змінна `app` буде «екземпляром» класу `FastAPI`.
### Крок 3: визначте операцію шляху (path operation)
Це буде головна точка взаємодії для створення всього вашого API.
#### Шлях (path)
### Крок 3: створіть *операцію шляху* { #step-3-create-a-path-operation }
"Шлях" це частина URL, яка йде одразу після символу `/`.
#### Шлях { #path }
«Шлях» тут означає останню частину URL, починаючи з першого `/`.
Отже, у такому URL, як:
@@ -192,16 +221,17 @@ https://example.com/items/foo
/items/foo
```
/// info | Додаткова інформація
/// info | Інформація
"Шлях" (path) також зазвичай називають "ендпоінтом" (endpoint) або "маршрутом" (route).
«Шлях» також зазвичай називають «ендпоінтом» або «маршрутом».
///
При створенні API, "шлях" є основним способом розділення "завдань" і "ресурсів".
#### Operation
Під час створення API «шлях» є основним способом розділити «завдання» і «ресурси».
"Операція" (operation) тут означає один з "методів" HTTP.
#### Операція { #operation }
«Операція» тут означає один з HTTP «методів».
Один з:
@@ -217,46 +247,47 @@ https://example.com/items/foo
* `PATCH`
* `TRACE`
У HTTP-протоколі можна спілкуватися з кожним шляхом, використовуючи один (або кілька) з цих "методів".
У протоколі HTTP ви можете спілкуватися з кожним шляхом, використовуючи один (або кілька) з цих «методів».
---
При створенні API зазвичай використовуються конкретні методи HTTP для виконання певних дій.
Під час створення API зазвичай використовують ці конкретні HTTP методи, щоб виконати певну дію.
Як правило, використовують:
Зазвичай використовують:
* `POST`: для створення даних.
* `GET`: для читання даних.
* `PUT`: для оновлення даних.
* `DELETE`: для видалення даних.
* `POST`: щоб створити дані.
* `GET`: щоб читати дані.
* `PUT`: щоб оновити дані.
* `DELETE`: щоб видалити дані.
В OpenAPI кожен HTTP метод називається "операція".
Отже, в OpenAPI кожен з HTTP методів називається «операцією».
Ми також будемо дотримуватися цього терміна.
Ми також будемо називати їх «**операціями**».
#### Визначте декоратор операції шляху (path operation decorator)
#### Визначте *декоратор операції шляху* { #define-a-path-operation-decorator }
{* ../../docs_src/first_steps/tutorial001.py hl[6] *}
Декоратор `@app.get("/")` вказує **FastAPI**, що функція нижче, відповідає за обробку запитів, які надходять до неї:
{* ../../docs_src/first_steps/tutorial001_py39.py hl[6] *}
* шлях `/`
Декоратор `@app.get("/")` повідомляє **FastAPI**, що функція одразу нижче відповідає за обробку запитів, які надходять до:
* шляху `/`
* використовуючи <abbr title="an HTTP GET method"><code>get</code> операцію</abbr>
/// info | `@decorator` Додаткова інформація
/// info | `@decorator` Інформація
Синтаксис `@something` у Python називається "декоратором".
Синтаксис `@something` у Python називається «декоратором».
Ви розташовуєте його над функцією. Як гарний декоративний капелюх (мабуть, звідти походить термін).
"Декоратор" приймає функцію нижче і виконує з нею якусь дію.
«Декоратор» бере функцію нижче і виконує з нею якусь дію.
У нашому випадку, цей декоратор повідомляє **FastAPI**, що функція нижче відповідає **шляху** `/` і **операції** `get`.
Це і є "декоратор операції шляху (path operation decorator)".
Це і є «**декоратор операції шляху**».
///
Можна також використовувати операції:
Можна також використовувати інші операції:
* `@app.post()`
* `@app.put()`
@@ -271,58 +302,79 @@ https://example.com/items/foo
/// tip | Порада
Ви можете використовувати кожну операцію (HTTP-метод) на свій розсуд.
Ви можете використовувати кожну операцію (HTTP-метод) як забажаєте.
**FastAPI** не нав'язує жодного певного значення для кожного методу.
**FastAPI** не навʼязує жодного конкретного значення.
Наведена тут інформація є рекомендацією, а не обов'язковою вимогою.
Наведена тут інформація подана як настанова, а не вимога.
Наприклад, під час використання GraphQL зазвичай усі дії виконуються тільки за допомогою `POST` операцій.
Наприклад, під час використання GraphQL ви зазвичай виконуєте всі дії, використовуючи лише `POST` операції.
///
### Крок 4: визначте **функцію операції шляху (path operation function)**
### Крок 4: визначте **функцію операції шляху** { #step-4-define-the-path-operation-function }
Ось "**функція операції шляху**":
Ось наша «**функція операції шляху**»:
* **шлях**: це `/`.
* **операція**: це `get`.
* **функція**: це функція, яка знаходиться нижче "декоратора" (нижче `@app.get("/")`).
* **функція**: це функція нижче «декоратора» (нижче `@app.get("/")`).
{* ../../docs_src/first_steps/tutorial001.py hl[7] *}
{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *}
Це звичайна функція Python.
Це функція Python.
FastAPI викликатиме її щоразу, коли отримає запит до URL із шляхом "/", використовуючи операцію `GET`.
**FastAPI** викликатиме її щоразу, коли отримає запит до URL «`/, використовуючи операцію `GET`.
У даному випадку це асинхронна функція.
У цьому випадку це `async` функція.
---
Ви також можете визначити її як звичайну функцію замість `async def`:
{* ../../docs_src/first_steps/tutorial003.py hl[7] *}
{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *}
/// note | Примітка
Якщо не знаєте в чому різниця, подивіться [Конкурентність: *"Поспішаєш?"*](../async.md#in-a-hurry){.internal-link target=_blank}.
Якщо ви не знаєте різницю, подивіться [Асинхронність: *«Поспішаєте?»*](../async.md#in-a-hurry){.internal-link target=_blank}.
///
### Крок 5: поверніть результат
### Крок 5: поверніть вміст { #step-5-return-the-content }
{* ../../docs_src/first_steps/tutorial001.py hl[8] *}
{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *}
Ви можете повернути `dict`, `list`, а також окремі значення `str`, `int`, ітд.
Ви можете повернути `dict`, `list`, а також окремі значення `str`, `int` тощо.
Також можна повернути моделі Pydantic (про це ви дізнаєтесь пізніше).
Існує багато інших об'єктів і моделей, які будуть автоматично конвертовані в JSON (зокрема ORM тощо). Спробуйте використати свої улюблені, велика ймовірність, що вони вже підтримуються.
Існує багато інших обʼєктів і моделей, які будуть автоматично конвертовані в JSON (зокрема ORM тощо). Спробуйте використати свої улюблені велика ймовірність, що вони вже підтримуються.
## Підіб'ємо підсумки
### Крок 6: розгорніть його { #step-6-deploy-it }
* Імпортуємо `FastAPI`.
* Створюємо екземпляр `app`.
* Пишемо **декоратор операції шляху** як `@app.get("/")`.
* Пишемо **функцію операції шляху**; наприклад, `def root(): ...`.
* Запускаємо сервер у режимі розробки `fastapi dev`.
Розгорніть ваш застосунок у **<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** однією командою: `fastapi deploy`. 🎉
#### Про FastAPI Cloud { #about-fastapi-cloud }
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** створено тим самим автором і командою, які стоять за **FastAPI**.
Він спрощує процес **створення**, **розгортання** та **доступу** до API з мінімальними зусиллями.
Він переносить той самий **досвід розробника** зі створення застосунків на FastAPI на **розгортання** їх у хмарі. 🎉
FastAPI Cloud — основний спонсор і джерело фінансування для open source проєктів *FastAPI and friends*. ✨
#### Розгортання в інших хмарних провайдерах { #deploy-to-other-cloud-providers }
FastAPI — це open source і базується на стандартах. Ви можете розгортати FastAPI-застосунки у будь-якого хмарного провайдера на ваш вибір.
Дотримуйтеся інструкцій вашого хмарного провайдера, щоб розгорнути FastAPI-застосунки з їхньою допомогою. 🤓
## Підібʼємо підсумки { #recap }
* Імпортуйте `FastAPI`.
* Створіть екземпляр `app`.
* Напишіть **декоратор операції шляху**, використовуючи декоратори на кшталт `@app.get("/")`.
* Визначте **функцію операції шляху**; наприклад, `def root(): ...`.
* Запустіть сервер розробки командою `fastapi dev`.
* За бажанням розгорніть ваш застосунок за допомогою `fastapi deploy`.

View File

@@ -1,10 +1,10 @@
# Обробка Помилок
# Обробка помилок { #handling-errors }
Є багато ситуацій, коли потрібно повідомити клієнта, який використовує Ваш API, про помилку.
Є багато ситуацій, коли вам потрібно повідомити про помилку клієнта, який використовує ваш API.
Цим клієнтом може бути браузер із фронтендом, код іншого розробника, IoT-пристрій тощо.
Можливо, Вам потрібно повідомити клієнта, що:
Можливо, вам потрібно повідомити клієнта, що:
* У нього недостатньо прав для виконання цієї операції.
* Він не має доступу до цього ресурсу.
@@ -13,37 +13,37 @@
У таких випадках зазвичай повертається **HTTP статус-код** в діапазоні **400** (від 400 до 499).
Це схоже на HTTP статус-коди 200 (від 200 до 299). Ці "200" статус-коди означають, що запит пройшов успішно.
Це схоже на HTTP статус-коди 200 (від 200 до 299). Ці «200» статус-коди означають, що якимось чином запит був «успішним».
Статус-коди в діапазоні 400 означають, що сталася помилка з боку клієнта.
Пам'ятаєте всі ці помилки **404 Not Found** (і жарти про них)?
Пам'ятаєте всі ці помилки **«404 Not Found»** (і жарти про них)?
## Використання `HTTPException`
## Використання `HTTPException` { #use-httpexception }
Щоб повернути HTTP-відповіді з помилками клієнту, використовуйте `HTTPException`.
### Імпорт `HTTPException`
### Імпорт `HTTPException` { #import-httpexception }
{* ../../docs_src/handling_errors/tutorial001.py hl[1] *}
{* ../../docs_src/handling_errors/tutorial001_py39.py hl[1] *}
### Використання `HTTPException` у коді
### Згенеруйте `HTTPException` у своєму коді { #raise-an-httpexception-in-your-code }
`HTTPException` — це звичайна помилка Python із додатковими даними, які стосуються API.
Оскільки це помилка Python, Ви не `повертаєте` його, а `генеруєте` (генеруєте помилку).
Оскільки це помилка Python, ви не `return` її, а `raise` її.
Це також означає, що якщо Ви перебуваєте всередині допоміжної функції, яку викликаєте всередині своєї *функції операції шляху*, і там генеруєте `HTTPException`, всередині цієї допоміжної функції, то решта коду в *функції операції шляху* не буде виконана. Запит одразу завершиться, і HTTP-помилка з `HTTPException` буде надіслана клієнту.
Це також означає, що якщо ви перебуваєте всередині допоміжної функції, яку викликаєте всередині своєї *функції операції шляху*, і там згенеруєте `HTTPException` всередині цієї допоміжної функції, то решта коду в *функції операції шляху* не буде виконана. Запит одразу завершиться, і HTTP-помилка з `HTTPException` буде надіслана клієнту.
Перевага використання `генерації` (raise) помилки замість `повернення` значення (return) стане більш очевидним в розділі про Залежності та Безпеку.
Перевага генерації виключення замість повернення значення стане більш очевидною в розділі про залежності та безпеку.
У цьому прикладі, якщо клієнт запитує елемент за ID, якого не існує, буде згенеровано помилку зі статус-кодом `404`:
У цьому прикладі, коли клієнт запитує елемент за ID, якого не існує, згенеруйте виключення зі статус-кодом `404`:
{* ../../docs_src/handling_errors/tutorial001.py hl[11] *}
{* ../../docs_src/handling_errors/tutorial001_py39.py hl[11] *}
### Отримана відповідь
### Отримана відповідь { #the-resulting-response }
Якщо клієнт робить запит за шляхом `http://example.com/items/foo` (де `item_id` `"foo"`), він отримає статус-код 200 і JSON відповідь:
Якщо клієнт робить запит за шляхом `http://example.com/items/foo` (де `item_id` `"foo"`), він отримає HTTP статус-код 200 і JSON відповідь:
```JSON
{
@@ -51,7 +51,7 @@
}
```
Але якщо клієнт робить запит на `http://example.com/items/bar` (де `item_id` має не існуюче значення `"bar"`), то отримає статус-код 404 (помилка "не знайдено") та відповідь:
Але якщо клієнт робить запит на `http://example.com/items/bar` (де `item_id` має не існуюче значення `"bar"`), то отримає HTTP статус-код 404 (помилка «не знайдено») та JSON відповідь:
```JSON
{
@@ -61,7 +61,7 @@
/// tip | Порада
Під час виклику `HTTPException` Ви можете передати будь-яке значення, яке може бути перетворене в JSON, як параметр `detail`, а не лише рядок (`str`).
Під час генерації `HTTPException` ви можете передати будь-яке значення, яке може бути перетворене в JSON, як параметр `detail`, а не лише `str`.
Ви можете передати `dict`, `list` тощо.
@@ -69,33 +69,33 @@
///
## Додавання власних заголовків
## Додавання власних заголовків { #add-custom-headers }
Іноді потрібно додати власні заголовки до HTTP-помилки, наприклад, для певних типів безпеки.
Є деякі ситуації, коли корисно мати можливість додавати власні заголовки до HTTP-помилки. Наприклад, для деяких типів безпеки.
Ймовірно, Вам не доведеться використовувати це безпосередньо у своєму коді.
Ймовірно, вам не доведеться використовувати це безпосередньо у своєму коді.
Але якщо Вам знадобиться це для складного сценарію, Ви можете додати власні заголовки:
Але якщо вам знадобиться це для складного сценарію, ви можете додати власні заголовки:
{* ../../docs_src/handling_errors/tutorial002.py hl[14] *}
{* ../../docs_src/handling_errors/tutorial002_py39.py hl[14] *}
## Встановлення власних обробників помилок
## Встановлення власних обробників виключень { #install-custom-exception-handlers }
Ви можете додати власні обробники помилок за допомогою <a href="https://www.starlette.dev/exceptions/" class="external-link" target="_blank">тих самих утиліт обробки помилок зі Starlette</a>.
Ви можете додати власні обробники виключень за допомогою <a href="https://www.starlette.dev/exceptions/" class="external-link" target="_blank">тих самих утиліт для виключень зі Starlette</a>.
Припустимо, у Вас є власний обʼєкт помилки `UnicornException`, яке Ви (або бібліотека, яку Ви використовуєте) може `згенерувати` (`raise`).
Припустімо, у вас є власне виключення `UnicornException`, яке ви (або бібліотека, яку ви використовуєте) можете `raise`.
І Ви хочете обробляти це виключення глобально за допомогою FastAPI.
І ви хочете обробляти це виключення глобально за допомогою FastAPI.
Ви можете додати власний обробник виключень за допомогою `@app.exception_handler()`:
{* ../../docs_src/handling_errors/tutorial003.py hl[5:7,13:18,24] *}
{* ../../docs_src/handling_errors/tutorial003_py39.py hl[5:7,13:18,24] *}
Тут, якщо Ви звернетеся до `/unicorns/yolo`, то згенерується помилка `UnicornException`.
Тут, якщо ви звернетеся до `/unicorns/yolo`, *операція шляху* згенерує (`raise`) `UnicornException`.
Але вона буде оброблена функцією-обробником `unicorn_exception_handler`.
Отже, Ви отримаєте зрозумілу помилку зі HTTP-статусом `418` і JSON-відповіддю:
Отже, ви отримаєте зрозумілу помилку зі HTTP-статусом `418` і JSON-вмістом:
```JSON
{"message": "Oops! yolo did something. There goes a rainbow..."}
@@ -105,31 +105,31 @@
Ви також можете використовувати `from starlette.requests import Request` і `from starlette.responses import JSONResponse`.
**FastAPI** надає ті самі `starlette.responses`, що й `fastapi.responses`, просто для зручності розробника. Але більшість доступних відповідей надходять безпосередньо зі Starlette. Те ж саме стосується і `Request`.
**FastAPI** надає ті самі `starlette.responses`, що й `fastapi.responses`, просто для зручності для вас, розробника. Але більшість доступних відповідей надходять безпосередньо зі Starlette. Те ж саме з `Request`.
///
## Перевизначення обробників помилок за замовчуванням
## Перевизначення обробників виключень за замовчуванням { #override-the-default-exception-handlers }
**FastAPI** має кілька обробників помилок за замовчуванням.
**FastAPI** має кілька обробників виключень за замовчуванням.
Ці обробники відповідають за повернення стандартних JSON-відповідей, коли Ви `генеруєте` (`raise`) `HTTPException`, а також коли запит містить некоректні дані.
Ці обробники відповідають за повернення стандартних JSON-відповідей, коли ви `raise` `HTTPException`, а також коли запит містить некоректні дані.
Ви можете перевизначити ці обробники, створивши власні.
Ви можете перевизначити ці обробники виключень власними.
### Перевизначення помилок валідації запиту
### Перевизначення виключень валідації запиту { #override-request-validation-exceptions }
Коли запит містить некоректні дані, **FastAPI** генерує `RequestValidationError`.
Коли запит містить некоректні дані, **FastAPI** внутрішньо генерує `RequestValidationError`.
І також включає обробник помилок за замовчуванням для нього.
І також включає обробник виключень за замовчуванням для нього.
Щоб перевизначити його, імпортуйте `RequestValidationError` і використовуйте його з `@app.exception_handler(RequestValidationError)` для декорування обробника помилок.
Щоб перевизначити його, імпортуйте `RequestValidationError` і використовуйте його з `@app.exception_handler(RequestValidationError)` для декорування обробника виключень.
Обробник помилок отримує `Request` і саму помилку.
Обробник виключень отримає `Request` і саме виключення.
{* ../../docs_src/handling_errors/tutorial004.py hl[2,14:16] *}
{* ../../docs_src/handling_errors/tutorial004_py39.py hl[2,14:19] *}
Тепер, якщо Ви перейдете за посиланням `/items/foo`, замість того, щоб отримати стандартну JSON-помилку:
Тепер, якщо ви перейдете за посиланням `/items/foo`, замість того, щоб отримати стандартну JSON-помилку:
```JSON
{
@@ -146,55 +146,44 @@
}
```
Ви отримаєте текстову версію:
ви отримаєте текстову версію:
```
1 validation error
path -> item_id
value is not a valid integer (type=type_error.integer)
Validation errors:
Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to parse string as an integer
```
#### `RequestValidationError` проти `ValidationError`
### Перевизначення обробника помилок `HTTPException` { #override-the-httpexception-error-handler }
/// warning | Увага
Аналогічно, ви можете перевизначити обробник `HTTPException`.
Це технічні деталі, які Ви можете пропустити, якщо вони зараз не важливі для Вас.
Наприклад, ви можете захотіти повернути відповідь у вигляді простого тексту замість JSON для цих помилок:
///
`RequestValidationError` є підкласом Pydantic <a href="https://docs.pydantic.dev/latest/concepts/models/#error-handling" class="external-link" target="_blank">`ValidationError`</a>.
**FastAPI** використовує його для того, якщо Ви використовуєте модель Pydantic у `response_model` і у ваших даних є помилка, Ви побачили помилку у своєму журналі.
Але клієнт/користувач не побачить її. Натомість клієнт отримає "Internal Server Error" зі статусом HTTP `500`.
Так має бути, якщо у Вас виникла `ValidationError` Pydantic у *відповіді* або деінде у вашому коді (не у *запиті* клієнта), це насправді є помилкою у Вашому коді.
І поки Ви її виправляєте, клієнти/користувачі не повинні мати доступу до внутрішньої інформації про помилку, оскільки це може призвести до вразливості безпеки.
### Перевизначення обробника помилок `HTTPException`
Аналогічно, Ви можете перевизначити обробник `HTTPException`.
Наприклад, Ви можете захотіти повернути текстову відповідь замість JSON для цих помилок:
{* ../../docs_src/handling_errors/tutorial004.py hl[3:4,9:11,22] *}
{* ../../docs_src/handling_errors/tutorial004_py39.py hl[3:4,9:11,25] *}
/// note | Технічні деталі
Ви також можете використовувати `from starlette.responses import PlainTextResponse`.
**FastAPI** надає ті самі `starlette.responses`, що й `fastapi.responses`, просто для зручності розробника. Але більшість доступних відповідей надходять безпосередньо зі Starlette.
**FastAPI** надає ті самі `starlette.responses`, що й `fastapi.responses`, просто для зручності для вас, розробника. Але більшість доступних відповідей надходять безпосередньо зі Starlette.
///
### Використання тіла `RequestValidationError`
/// warning | Попередження
Пам’ятайте, що `RequestValidationError` містить інформацію про назву файлу та рядок, де сталася помилка валідації, щоб за потреби ви могли показати це у своїх логах із відповідною інформацією.
Але це означає, що якщо ви просто перетворите це на рядок і повернете цю інформацію напряму, ви можете розкрити трохи інформації про вашу систему, тому тут код витягає та показує кожну помилку незалежно.
///
### Використання тіла `RequestValidationError` { #use-the-requestvalidationerror-body }
`RequestValidationError` містить `body`, який він отримав із некоректними даними.
Ви можете використовувати це під час розробки свого додатка, щоб логувати тіло запиту та налагоджувати його, повертати користувачеві тощо.
{* ../../docs_src/handling_errors/tutorial005.py hl[14] *}
{* ../../docs_src/handling_errors/tutorial005_py39.py hl[14] *}
Тепер спробуйте надіслати некоректний елемент, наприклад:
@@ -204,8 +193,8 @@ path -> item_id
"size": "XL"
}
```
Ви отримаєте відповідь, яка повідомить Вам, які саме дані є некоректні у вашому тілі запиту:
Ви отримаєте відповідь, яка повідомить вам, що дані є некоректними, і міститиме отримане тіло запиту:
```JSON hl_lines="12-15"
{
@@ -226,30 +215,30 @@ path -> item_id
}
```
#### `HTTPException` FastAPI проти `HTTPException` Starlette
#### `HTTPException` FastAPI проти `HTTPException` Starlette { #fastapis-httpexception-vs-starlettes-httpexception }
**FastAPI** має власний `HTTPException`.
І клас помилки `HTTPException` в **FastAPI** успадковується від класу помилки `HTTPException` в Starlette.
І клас помилки `HTTPException` в **FastAPI** успадковується від класу помилки `HTTPException` у Starlette.
Єдина різниця полягає в тому, що `HTTPException` в **FastAPI** приймає будь-які дані, які можна перетворити на JSON, для поля `detail`, тоді як `HTTPException` у Starlette приймає тільки рядки.
Отже, Ви можете продовжувати використовувати `HTTPException` в **FastAPI** як зазвичай у своєму коді.
Отже, ви можете продовжувати генерувати `HTTPException` **FastAPI** як зазвичай у своєму коді.
Але коли Ви реєструєте обробник виключень, слід реєструвати його для `HTTPException` зі Starlette.
Але коли ви реєструєте обробник виключень, слід реєструвати його для `HTTPException` зі Starlette.
Таким чином, якщо будь-яка частина внутрішнього коду Starlette або розширення чи плагін Starlette згенерує (raise) `HTTPException`, Ваш обробник зможе перехопити та обробити її.
Таким чином, якщо будь-яка частина внутрішнього коду Starlette або розширення чи плагін Starlette згенерує Starlette `HTTPException`, ваш обробник зможе перехопити та обробити її.
У цьому прикладі, щоб мати можливість використовувати обидва `HTTPException` в одному коді, помилка Starlette перейменовується на `StarletteHTTPException`:
У цьому прикладі, щоб мати можливість використовувати обидва `HTTPException` в одному коді, виключення Starlette перейменовується на `StarletteHTTPException`:
```Python
from starlette.exceptions import HTTPException as StarletteHTTPException
```
### Повторне використання обробників помилок **FastAPI**
### Повторне використання обробників виключень **FastAPI** { #reuse-fastapis-exception-handlers }
Якщо Ви хочете використовувати помилки разом із такими ж обробниками помилок за замовчуванням, як у **FastAPI**, Ви можете імпортувати та повторно використовувати їх із `fastapi.exception_handlers`:
Якщо ви хочете використовувати виключення разом із такими ж обробниками виключень за замовчуванням, як у **FastAPI**, ви можете імпортувати та повторно використати обробники виключень за замовчуванням із `fastapi.exception_handlers`:
{* ../../docs_src/handling_errors/tutorial006.py hl[2:5,15,21] *}
{* ../../docs_src/handling_errors/tutorial006_py39.py hl[2:5,15,21] *}
У цьому прикладі Ви просто використовуєте `print` для виведення дуже інформативного повідомлення, але Ви зрозуміли основну ідею. Ви можете обробити помилку та повторно використовувати обробники помилок за замовчуванням.
У цьому прикладі ви просто друкуєте помилку з дуже виразним повідомленням, але ви зрозуміли основну ідею. Ви можете використовувати виключення, а потім просто повторно використати обробники виключень за замовчуванням.

View File

@@ -1,26 +1,24 @@
# Моделі Параметрів Заголовків
# Моделі параметрів заголовків { #header-parameter-models }
Якщо у Вас є група пов’язаних параметрів заголовків, Ви можете створити **Pydantic модель** для їх оголошення.
Якщо у Вас є група пов’язаних **параметрів заголовків**, Ви можете створити **Pydantic модель** для їх оголошення.
Це дозволить Вам повторно **використовувати модель** в **різних місцях**, а також оголосити валідації та метадані для всіх параметрів одночасно. 😎
/// note | Нотатки
/// note | Примітка
Ця можливість підтримується починаючи з версії FastAPI `0.115.0`. 🤓
///
## Параметри Заголовків з Використанням Pydantic Model
## Параметри заголовків з використанням Pydantic моделі { #header-parameters-with-a-pydantic-model }
Оголосіть потрібні **параметри заголовків** у **Pydantic моделі**, а потім оголосіть параметр як `Header`:
{* ../../docs_src/header_param_models/tutorial001_an_py310.py hl[9:14,18] *}
FastAPI буде витягувати дані для кожного поля з заголовків у запиті та передавати їх у створену Вами Pydantic модель.
**FastAPI** буде **витягувати** дані для **кожного поля** з **заголовків** у запиті та передавати їх у створену Вами Pydantic модель.
## Перевірка в Документації
## Перевірка в документації { #check-the-docs }
Ви можете побачити необхідні заголовки в інтерфейсі документації за адресою `/docs`:
@@ -28,7 +26,7 @@ FastAPI буде витягувати дані для кожного поля з
<img src="/img/tutorial/header-param-models/image01.png">
</div>
## Заборона Додаткових Заголовків
## Заборонити додаткові заголовки { #forbid-extra-headers }
У деяких особливих випадках (ймовірно, не дуже поширених) Ви можете захотіти **обмежити** заголовки, які хочете отримати.
@@ -38,7 +36,7 @@ FastAPI буде витягувати дані для кожного поля з
Якщо клієнт спробує надіслати **додаткові заголовки**, він отримає **помилку** у відповіді.
Наприклад, якщо клієнт спробує надіслати заголовок `tool` зі значенням `plumbus`, він отримає **помилку** з повідомленням про те, що параметр заголовка `tool` не дозволений:
Наприклад, якщо клієнт спробує надіслати заголовок `tool` зі значенням `plumbus`, він отримає **помилку** у відповіді з повідомленням про те, що параметр заголовка `tool` не дозволений:
```json
{
@@ -53,6 +51,22 @@ FastAPI буде витягувати дані для кожного поля з
}
```
## Підсумок
## Вимкнути перетворення підкреслень { #disable-convert-underscores }
Так само, як і зі звичайними параметрами заголовків, коли у назвах параметрів є символи підкреслення, вони **автоматично перетворюються на дефіси**.
Наприклад, якщо у коді у Вас є параметр заголовка `save_data`, очікуваний HTTP-заголовок буде `save-data`, і він так само відображатиметься в документації.
Якщо з якоїсь причини Вам потрібно вимкнути це автоматичне перетворення, Ви також можете зробити це для Pydantic моделей для параметрів заголовків.
{* ../../docs_src/header_param_models/tutorial003_an_py310.py hl[19] *}
/// warning | Попередження
Перш ніж встановлювати `convert_underscores` у значення `False`, пам’ятайте, що деякі HTTP проксі та сервери забороняють використання заголовків із підкресленнями.
///
## Підсумок { #summary }
Ви можете використовувати **Pydantic моделі** для оголошення **заголовків** у **FastAPI**. 😎

View File

@@ -1,14 +1,14 @@
# Header-параметри
# Параметри заголовків { #header-parameters }
Ви можете визначати параметри заголовків, так само як визначаєте `Query`, `Path` і `Cookie` параметри.
Ви можете визначати параметри заголовків так само, як визначаєте параметри `Query`, `Path` і `Cookie`.
## Імпорт `Header`
## Імпорт `Header` { #import-header }
Спочатку імпортуйте `Header`:
{* ../../docs_src/header_params/tutorial001_an_py310.py hl[3] *}
## Оголошення параметрів `Header`
## Оголошення параметрів `Header` { #declare-header-parameters }
Потім оголосіть параметри заголовків, використовуючи ту ж структуру, що й для `Path`, `Query` та `Cookie`.
@@ -18,9 +18,9 @@
/// note | Технічні деталі
`Header`є "сестринським" класом для `Path`, `Query` і `Cookie`. Він також успадковується від загального класу `Param`.
`Header` є «сестринським» класом для `Path`, `Query` і `Cookie`. Він також успадковується від того ж спільного класу `Param`.
Але пам’ятайте, що при імпорті `Query`, `Path`, `Header` та інших із `fastapi`, то насправді вони є функціями, які повертають спеціальні класи.
Але пам’ятайте, що коли ви імпортуєте `Query`, `Path`, `Header` та інші з `fastapi`, то насправді це функції, які повертають спеціальні класи.
///
@@ -30,43 +30,43 @@
///
## Автоматичне перетворення
## Автоматичне перетворення { #automatic-conversion }
`Header` має додатковий функціонал порівняно з `Path`, `Query` та `Cookie`.
`Header` має трохи додаткової функціональності порівняно з тим, що надають `Path`, `Query` та `Cookie`.
Більшість стандартних заголовків розділяються символом «дефіс», також відомим як «мінус» (`-`).
Більшість стандартних заголовків розділяються символом «дефіс», також відомим як «символ мінуса» (`-`).
Але змінна, така як `user-agent`, є недійсною в Python.
Тому, за замовчуванням, `Header` автоматично перетворює символи підкреслення (`_`) на дефіси (`-`) для отримання та документування заголовків.
Тому, за замовчуванням, `Header` перетворюватиме символи підкреслення (`_`) у назвах параметрів на дефіси (`-`), щоб отримувати та документувати заголовки.
Оскільки заголовки HTTP не чутливі до регістру, Ви можете використовувати стандартний стиль Python ("snake_case").
Також заголовки HTTP не чутливі до регістру, тож ви можете оголошувати їх у стандартному стилі Python (також відомому як «snake_case»).
Тому Ви можете використовувати `user_agent`, як зазвичай у коді Python, замість того щоб писати з великої літери, як `User_Agent` або щось подібне.
Тому ви можете використовувати `user_agent`, як зазвичай у коді Python, замість того щоб потрібно було писати з великої літери перші літери, як `User_Agent` або щось подібне.
Якщо Вам потрібно вимкнути автоматичне перетворення підкреслень у дефіси, встановіть `convert_underscores` в `Header` значення `False`:
Якщо з якоїсь причини вам потрібно вимкнути автоматичне перетворення підкреслень на дефіси, встановіть параметр `convert_underscores` у `Header` в `False`:
{* ../../docs_src/header_params/tutorial002_an_py310.py hl[10] *}
/// warning | Увага
/// warning | Попередження
Перед тим як встановити значення `False` для `convert_underscores` пам’ятайте, що деякі HTTP-проксі та сервери не підтримують заголовки з підкресленнями.
Перед тим як встановити `convert_underscores` в `False`, пам’ятайте, що деякі HTTP-проксі та сервери забороняють використання заголовків із підкресленнями.
///
## Дубльовані заголовки
## Дубльовані заголовки { #duplicate-headers }
Можливо отримати дубльовані заголовки, тобто той самий заголовок із кількома значеннями.
Можливо отримати дубльовані заголовки. Тобто один і той самий заголовок із кількома значеннями.
Це можна визначити, використовуючи список у типізації параметра.
Ви можете визначити такі випадки, використовуючи список у типізації.
Ви отримаєте всі значення дубльованого заголовка у вигляді `list` у Python.
Ви отримаєте всі значення дубльованого заголовка у вигляді Python-`list`.
Наприклад, щоб оголосити заголовок `X-Token`, який може з’являтися більше ніж один раз:
Наприклад, щоб оголосити заголовок `X-Token`, який може з’являтися більше ніж один раз, ви можете написати:
{* ../../docs_src/header_params/tutorial003_an_py310.py hl[9] *}
Якщо Ви взаємодієте з цією операцією шляху, надсилаючи два HTTP-заголовки, наприклад:
Якщо ви взаємодієте з цією *операцією шляху*, надсилаючи два HTTP-заголовки, наприклад:
```
X-Token: foo
@@ -84,8 +84,8 @@ X-Token: bar
}
```
## Підсумок
## Підсумок { #recap }
Оголошуйте заголовки за допомогою `Header`, використовуючи той самий підхід, що й для `Query`, `Path` та `Cookie`.
Оголошуйте заголовки за допомогою `Header`, використовуючи той самий загальний підхід, що й для `Query`, `Path` та `Cookie`.
Не хвилюйтеся про підкреслення у змінних — **FastAPI** автоматично конвертує їх.
І не хвилюйтеся про підкреслення у ваших змінних — **FastAPI** подбає про їх перетворення.

View File

@@ -1,29 +1,53 @@
# Туторіал - Посібник користувача
# Туторіал - Посібник користувача { #tutorial-user-guide }
У цьому посібнику показано, як користуватися **FastAPI** з більшістю його функцій, крок за кроком.
Кожен розділ поступово надбудовується на попередні, але він структурований на окремі теми, щоб ви могли перейти безпосередньо до будь-якої конкретної, щоб вирішити ваші конкретні потреби API.
Він також створений як довідник для роботи у майбутньому.
Також він створений як довідник для роботи у майбутньому, тож ви можете повернутися і побачити саме те, що вам потрібно.
Тож ви можете повернутися і побачити саме те, що вам потрібно.
## Запустіть код
## Запустіть код { #run-the-code }
Усі блоки коду можна скопіювати та використовувати безпосередньо (це фактично перевірені файли Python).
Щоб запустити будь-який із прикладів, скопіюйте код у файл `main.py` і запустіть `uvicorn` за допомогою:
Щоб запустити будь-який із прикладів, скопіюйте код у файл `main.py` і запустіть `fastapi dev` за допомогою:
<div class="termy">
```console
$ uvicorn main:app --reload
$ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:solid">main.py</u>
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
<span style="color: green;">INFO</span>: Started reloader process [28720]
<span style="color: green;">INFO</span>: Started server process [28722]
<span style="color: green;">INFO</span>: Waiting for application startup.
<span style="color: green;">INFO</span>: Application startup complete.
<span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span> Starting development server 🚀
Searching for package file structure from directories
with <font color="#3465A4">__init__.py</font> files
Importing from <font color="#75507B">/home/user/code/</font><font color="#AD7FA8">awesomeapp</font>
<span style="background-color:#007166"><font color="#D3D7CF"> module </font></span> 🐍 main.py
<span style="background-color:#007166"><font color="#D3D7CF"> code </font></span> Importing the FastAPI app object from the module with
the following code:
<u style="text-decoration-style:solid">from </u><u style="text-decoration-style:solid"><b>main</b></u><u style="text-decoration-style:solid"> import </u><u style="text-decoration-style:solid"><b>app</b></u>
<span style="background-color:#007166"><font color="#D3D7CF"> app </font></span> Using import string: <font color="#3465A4">main:app</font>
<span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Server started at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font>
<span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Documentation at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000/docs</u></font>
<span style="background-color:#007166"><font color="#D3D7CF"> tip </font></span> Running in development mode, for production use:
<b>fastapi run</b>
Logs:
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Will watch for changes in these directories:
<b>[</b><font color="#4E9A06">&apos;/home/user/code/awesomeapp&apos;</font><b>]</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Uvicorn running on <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font> <b>(</b>Press CTRL+C
to quit<b>)</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started reloader process <b>[</b><font color="#34E2E2"><b>383138</b></font><b>]</b> using WatchFiles
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>383153</b></font><b>]</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
```
</div>
@@ -34,45 +58,33 @@ $ uvicorn main:app --reload
---
## Встановлення FastAPI
## Встановлення FastAPI { #install-fastapi }
Першим кроком є встановлення FastAPI.
Для туторіалу ви можете встановити його з усіма необов’язковими залежностями та функціями:
Переконайтеся, що ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його, а потім **встановіть FastAPI**:
<div class="termy">
```console
$ pip install "fastapi[all]"
$ pip install "fastapi[standard]"
---> 100%
```
</div>
...який також включає `uvicorn`, який ви можете використовувати як сервер, який запускає ваш код.
/// note | Примітка
/// note
Коли ви встановлюєте через `pip install "fastapi[standard]"`, він постачається з деякими типовими необов’язковими стандартними залежностями, включно з `fastapi-cloud-cli`, який дозволяє розгортати в <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>.
Ви також можете встановити його частина за частиною.
Якщо ви не хочете мати ці необов’язкові залежності, натомість можете встановити `pip install fastapi`.
Це те, що ви, ймовірно, зробили б, коли захочете розгорнути свою програму у виробничому середовищі:
```
pip install fastapi
```
Також встановіть `uvicorn`, щоб він працював як сервер:
```
pip install "uvicorn[standard]"
```
І те саме для кожної з опціональних залежностей, які ви хочете використовувати.
Якщо ви хочете встановити стандартні залежності, але без `fastapi-cloud-cli`, ви можете встановити через `pip install "fastapi[standard-no-fastapi-cloud-cli]"`.
///
## Розширений посібник користувача
## Розширений посібник користувача { #advanced-user-guide }
Існує також **Розширений посібник користувача**, який ви зможете прочитати пізніше після цього **Туторіал - Посібник користувача**.
@@ -80,4 +92,4 @@ pip install "uvicorn[standard]"
Але вам слід спочатку прочитати **Туторіал - Посібник користувача** (те, що ви зараз читаєте).
Він розроблений таким чином, що ви можете створити повну програму лише за допомогою **Туторіал - Посібник користувача**, а потім розширити її різними способами, залежно від ваших потреб, використовуючи деякі з додаткових ідей з **Розширеного посібника користувача** .
Він розроблений таким чином, що ви можете створити повну програму лише за допомогою **Туторіал - Посібник користувача**, а потім розширити її різними способами, залежно від ваших потреб, використовуючи деякі з додаткових ідей з **Розширеного посібника користувача**.

View File

@@ -1,26 +1,26 @@
# Метадані та URL-адреси документації
# Метадані та URL-адреси документації { #metadata-and-docs-urls }
Ви можете налаштувати кілька конфігурацій метаданих у Вашому додатку **FastAPI**.
## Метадані для API
## Метадані для API { #metadata-for-api }
Ви можете встановити такі поля, які використовуються в специфікації OpenAPI та в автоматично згенерованих інтерфейсах документації API:
| Параметр | Тип | Опис |
|------------|------|-------------|
| `title` | `str` | Назва API. |
| `summary` | `str` | Короткий опис API. <small>Доступно з OpenAPI 3.1.0, FastAPI 0.99.0.</small> |
| `description` | `str` | Більш детальний опис API. Може використовувати Markdown. |
| `summary` | `str` | Короткий підсумок API. <small>Доступно з OpenAPI 3.1.0, FastAPI 0.99.0.</small> |
| `description` | `str` | Короткий опис API. Може використовувати Markdown. |
| `version` | `string` | Версія API. Це версія Вашого додатка, а не OpenAPI. Наприклад, `2.5.0`. |
| `terms_of_service` | `str` | URL до умов використання API. Якщо вказано, має бути у форматі URL. |
| `contact` | `dict` | Інформація для контакту з API. Може містити кілька полів. <details><summary><code>contact</code> поля</summary><table><thead><tr><th>Параметр</th><th>Тип</th><th>Опис</th></tr></thead><tbody><tr><td><code>name</code></td><td><code>str</code></td><td>Ім'я контактної особи або організації.</td></tr><tr><td><code>url</code></td><td><code>str</code></td><td>URL з інформацією для контакту. Повинен бути у форматі URL.</td></tr><tr><td><code>email</code></td><td><code>str</code></td><td>Email контактної особи або організації. Повинен бути у форматі електронної пошти.</td></tr></tbody></table></details> |
| `license_info` | `dict` | Інформація про ліцензію для API. Може містити кілька полів. <details><summary><code>license_info</code> поля</summary><table><thead><tr><th>Параметр</th><th>Тип</th><th>Опис</th></tr></thead><tbody><tr><td><code>name</code></td><td><code>str</code></td><td><strong>ОБОВ'ЯЗКОВО</strong> (якщо встановлено <code>license_info</code>). Назва ліцензії для API.</td></tr><tr><td><code>identifier</code></td><td><code>str</code></td><td>Ліцензійний вираз за <a href="https://spdx.org/licenses/" class="external-link" target="_blank">SPDX</a> для API. Поле <code>identifier</code> взаємовиключне з полем <code>url</code>. <small>Доступно з OpenAPI 3.1.0, FastAPI 0.99.0.</small></td></tr><tr><td><code>url</code></td><td><code>str</code></td><td>URL до ліцензії, яка використовується для API. Повинен бути у форматі URL.</td></tr></tbody></table></details> |
| `terms_of_service` | `str` | URL до умов використання API. Якщо вказано, має бути у форматі URL. |
| `contact` | `dict` | Інформація для контакту з опублікованим API. Може містити кілька полів. <details><summary><code>contact</code> поля</summary><table><thead><tr><th>Параметр</th><th>Тип</th><th>Опис</th></tr></thead><tbody><tr><td><code>name</code></td><td><code>str</code></td><td>Ідентифікаційне ім'я контактної особи або організації.</td></tr><tr><td><code>url</code></td><td><code>str</code></td><td>URL, що вказує на контактну інформацію. <strong>МАЄ</strong> бути у форматі URL.</td></tr><tr><td><code>email</code></td><td><code>str</code></td><td>Адреса електронної пошти контактної особи або організації. <strong>МАЄ</strong> бути у форматі адреси електронної пошти.</td></tr></tbody></table></details> |
| `license_info` | `dict` | Інформація про ліцензію для опублікованого API. Може містити кілька полів. <details><summary><code>license_info</code> поля</summary><table><thead><tr><th>Параметр</th><th>Тип</th><th>Опис</th></tr></thead><tbody><tr><td><code>name</code></td><td><code>str</code></td><td><strong>ОБОВ'ЯЗКОВО</strong> (якщо встановлено <code>license_info</code>). Назва ліцензії для API.</td></tr><tr><td><code>identifier</code></td><td><code>str</code></td><td>Ліцензійний вираз за <a href="https://spdx.org/licenses/" class="external-link" target="_blank">SPDX</a> для API. Поле <code>identifier</code> взаємовиключне з полем <code>url</code>. <small>Доступно з OpenAPI 3.1.0, FastAPI 0.99.0.</small></td></tr><tr><td><code>url</code></td><td><code>str</code></td><td>URL до ліцензії, яка використовується для API. <strong>МАЄ</strong> бути у форматі URL.</td></tr></tbody></table></details> |
Ви можете налаштувати їх наступним чином:
{* ../../docs_src/metadata/tutorial001.py hl[3:16, 19:32] *}
{* ../../docs_src/metadata/tutorial001_py39.py hl[3:16, 19:32] *}
/// tip | Підказка
/// tip | Порада
У полі `description` можна використовувати Markdown, і він буде відображатися у результаті.
@@ -30,15 +30,15 @@
<img src="/img/tutorial/metadata/image01.png">
## Ідентифікатор ліцензії
## Ідентифікатор ліцензії { #license-identifier }
З початку використання OpenAPI 3.1.0 та FastAPI 0.99.0 Ви також можете налаштувати `license_info` за допомогою `identifier` замість `url`.
Наприклад:
{* ../../docs_src/metadata/tutorial001_1.py hl[31] *}
{* ../../docs_src/metadata/tutorial001_1_py39.py hl[31] *}
## Метадані для тегів
## Метадані для тегів { #metadata-for-tags }
Ви також можете додати додаткові метадані для різних тегів, які використовуються для групування операцій шляхів, за допомогою параметра `openapi_tags`.
@@ -46,53 +46,53 @@
Кожен словник може містити:
* `name` (**обов'язково**): `str` з тією ж назвою тегу, яку Ви використовуєте у параметрі `tags` у Ваших *операціях шляху* та `APIRouter`s.
* `description`: `str` з коротким описом тегу. Може містити Markdown і буде відображено в інтерфейсі документації.
* `externalDocs`: `dict` який описує зовнішню документацію з такими полями:
* `name` (**обов'язково**): `str` з тією ж назвою тегу, яку Ви використовуєте у параметрі `tags` у Ваших *операціях шляху* та `APIRouter`s.
* `description`: `str` з коротким описом тегу. Може містити Markdown і буде показано в інтерфейсі документації.
* `externalDocs`: `dict`, який описує зовнішню документацію з такими полями:
* `description`: `str` з коротким описом зовнішньої документації.
* `url` (**обов'язково**): `str`з URL-адресою зовнішньої документації.
* `url` (**обов'язково**): `str` з URL-адресою зовнішньої документації.
### Створення метаданих для тегів
### Створення метаданих для тегів { #create-metadata-for-tags }
Спробуймо це на прикладі з тегами для `users` та `items`.
Створіть метадані для своїх тегів і передайте їх у параметр `openapi_tags`:
Створіть метадані для своїх тегів і передайте їх у параметр `openapi_tags`:
{* ../../docs_src/metadata/tutorial004.py hl[3:16,18] *}
{* ../../docs_src/metadata/tutorial004_py39.py hl[3:16,18] *}
Зверніть увагу, що в описах можна використовувати Markdown, наприклад, "login" буде показано жирним шрифтом (**login**), а "fancy" буде показано курсивом (_fancy_).
/// tip | Порада
Не обов'язково додавати метадані для всіх тегів, які Ви використовуєте.
Вам не потрібно додавати метадані для всіх тегів, які Ви використовуєте.
///
### Використання тегів
### Використовуйте свої теги { #use-your-tags }
Використовуйте параметр `tags` зі своїми *операціями шляху* (і `APIRouter`) для призначення їх до різних тегів:
Використовуйте параметр `tags` зі своїми *операціями шляху* (і `APIRouter`s), щоб призначити їх до різних тегів:
{* ../../docs_src/metadata/tutorial004.py hl[21,26] *}
{* ../../docs_src/metadata/tutorial004_py39.py hl[21,26] *}
/// info | Інформація
Детальніше про теги читайте в розділі [Конфігурація шляхів операцій](path-operation-configuration.md#tags){.internal-link target=_blank}.
Детальніше про теги читайте в розділі [Конфігурація операції шляху](path-operation-configuration.md#tags){.internal-link target=_blank}.
///
### Перевірка документації
### Перевірте документацію { #check-the-docs }
Якщо Ви зараз перевірите документацію, вона покаже всі додаткові метадані:
Тепер, якщо Ви перевірите документацію, вона покаже всі додаткові метадані:
<img src="/img/tutorial/metadata/image02.png">
### Порядок тегів
### Порядок тегів { #order-of-tags }
Порядок кожного словника метаданих тегу також визначає порядок відображення в інтерфейсі документації.
Наприклад, хоча `users` мав би йти після `items` в алфавітному порядку, він відображається перед ними, оскільки ми додали його метадані як перший словник у списку.
Наприклад, хоча `users` мав би йти після `items` в алфавітному порядку, він відображається перед ними, оскільки ми додали їхні метадані як перший словник у списку.
## URL для OpenAPI
## URL для OpenAPI { #openapi-url }
За замовчуванням схема OpenAPI надається за адресою `/openapi.json`.
@@ -100,11 +100,11 @@
Наприклад, щоб налаштувати його на `/api/v1/openapi.json`:
{* ../../docs_src/metadata/tutorial002.py hl[3] *}
{* ../../docs_src/metadata/tutorial002_py39.py hl[3] *}
Якщо Ви хочете повністю вимкнути схему OpenAPI, Ви можете встановити `openapi_url=None`, це також вимкне інтерфейси документації, які її використовують.
## URL-адреси документації
## URL-адреси документації { #docs-urls }
Ви можете налаштувати два інтерфейси користувача для документації, які включені:
@@ -117,4 +117,4 @@
Наприклад, щоб налаштувати Swagger UI на `/documentation` і вимкнути ReDoc:
{* ../../docs_src/metadata/tutorial003.py hl[3] *}
{* ../../docs_src/metadata/tutorial003_py39.py hl[3] *}

View File

@@ -1,45 +1,43 @@
# Middleware (Проміжний шар)
# Middleware { #middleware }
У **FastAPI** можна додавати middleware (проміжний шар).
У **FastAPI** можна додавати middleware.
"Middleware" — це функція, яка працює з кожним **запитом** перед його обробкою будь-якою конкретною *операцією шляху* (*path operation*), а також з кожною **відповіддю** перед її поверненням.
«Middleware» — це функція, яка працює з кожним **запитом** перед його обробкою будь-якою конкретною *операцією шляху*. А також з кожною **відповіддю** перед її поверненням.
* Middleware отримує кожен **запит**, що надходить до Вашого застосунку.
* Може виконати певні дії із цим **запитом** або запустити необхідний код.
* Далі передає **запит** для обробки основним застосунком (*операцією шляху*).
* Отримує **відповідь**, сформовану застосунком (*операцією шляху*).
* Може змінити цю **відповідь** або виконати додатковий код.
* Повертає **відповідь** клієнту.
* Вона отримує кожен **запит**, що надходить до вашого застосунку.
* Потім вона може виконати певні дії із цим **запитом** або запустити необхідний код.
* Далі вона передає **запит** для обробки рештою застосунку (якоюсь *операцією шляху*).
* Потім вона отримує **відповідь**, сформовану застосунком (якоюсь *операцією шляху*).
* Вона може виконати певні дії із цією **відповіддю** або запустити необхідний код.
* Потім вона повертає **відповідь**.
/// note | Технічні деталі
Якщо у Вас є залежності з `yield`, код виходу виконається *після* middleware.
Якщо у вас є залежності з `yield`, код виходу виконається *після* middleware.
Якщо були заплановані фонові задачі (background tasks - розглянуто далі), вони виконаються *після* всіх middleware.
Якщо були заплановані фонові задачі (розглянуто в розділі [Background Tasks](background-tasks.md){.internal-link target=_blank}, ви побачите це пізніше), вони виконаються *після* всіх middleware.
///
## Створення middleware
## Створення middleware { #create-a-middleware }
Щоб створити middleware, Ви використовуєте декоратор `@app.middleware("http")` на функції.
Щоб створити middleware, ви використовуєте декоратор `@app.middleware("http")` над функцією.
Функція middleware отримує:
* `Запит`.
* Функцію `call_next`, яка приймає `запит` як параметр.
* Ця функція передає `запит` відповідній *операції шляху*.
* Потім вона повертає `відповідь`, згенеровану цією *операцією шляху*.
* `request`.
* Функцію `call_next`, яка отримає `request` як параметр.
* Ця функція передасть `request` відповідній *операції шляху*.
* Потім вона поверне `response`, згенеровану відповідною *операцією шляху*.
* Потім ви можете додатково змінити `response` перед тим, як повернути її.
* Ви можете ще змінити `відповідь` перед тим, як повернути її.
{* ../../docs_src/middleware/tutorial001.py hl[8:9,11,14] *}
{* ../../docs_src/middleware/tutorial001_py39.py hl[8:9,11,14] *}
/// tip | Порада
Не забувайте, що власні заголовки можна додавати, використовуючи <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">префікс 'X-'</a>.
Пам’ятайте, що власні пропрієтарні заголовки можна додавати <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">використовуючи префікс `X-`</a>.
Але якщо у Вас є власні заголовки, які Ви хочете, щоб браузерний клієнт міг побачити, потрібно додати їх до Вашої конфігурації CORS (див. [CORS (Обмін ресурсами між різними джерелами)](cors.md){.internal-link target=_blank} за допомогою параметра `expose_headers`, описаного в <a href="https://www.starlette.dev/middleware/#corsmiddleware" class="external-link" target="_blank">документації Starlette по CORS</a>.
Але якщо у вас є власні заголовки, які ви хочете, щоб клієнт у браузері міг побачити, потрібно додати їх до ваших конфігурацій CORS ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) за допомогою параметра `expose_headers`, описаного в <a href="https://www.starlette.dev/middleware/#corsmiddleware" class="external-link" target="_blank">документації Starlette по CORS</a>.
///
@@ -47,28 +45,50 @@
Ви також можете використати `from starlette.requests import Request`.
**FastAPI** надає це для Вашої зручності як розробника. Але він походить безпосередньо зі Starlette.
**FastAPI** надає це для вашої зручності як розробника. Але воно походить безпосередньо зі Starlette.
///
### До і після `response`(`відповіді`)
### До і після `response` { #before-and-after-the-response }
Ви можете додати код, який буде виконуватися з `запитом` (`request`), до того, як його обробить будь-яка *операція шляху* (*path operation*).
Ви можете додати код, який буде виконуватися з `request`, до того, як його отримає будь-яка *операція шляху*.
Також Ви можете додати код, який буде виконуватися після того, як `відповідь` (`response`) буде згенеровано, перед тим як його повернути.
Також ви можете додати код, який буде виконуватися після того, як `response` буде згенеровано, перед тим як її повернути.
Наприклад, Ви можете додати власний заголовок `X-Process-Time`, який міститиме час у секундах, який витратився на обробку запиту та генерацію відповіді:
Наприклад, ви можете додати власний заголовок `X-Process-Time`, який міститиме час у секундах, який витратився на обробку запиту та генерацію відповіді:
{* ../../docs_src/middleware/tutorial001.py hl[10,12:13] *}
{* ../../docs_src/middleware/tutorial001_py39.py hl[10,12:13] *}
/// tip | Підказка
/// tip | Порада
Тут ми використовуємо <a href="https://docs.python.org/3/library/time.html#time.perf_counter" class="external-link" target="_blank">`time.perf_counter()`</a> замість `time.time()` оскільки він може бути більш точним для таких випадків. 🤓
///
## Інші middlewares
## Порядок виконання кількох middleware { #multiple-middleware-execution-order }
Коли ви додаєте кілька middleware, використовуючи або декоратор `@app.middleware()` або метод `app.add_middleware()`, кожен новий middleware обгортає застосунок, утворюючи стек. Останній доданий middleware є *зовнішнім*, а перший — *внутрішнім*.
На шляху запиту першим виконується *зовнішній* middleware.
На шляху відповіді він виконується останнім.
Наприклад:
```Python
app.add_middleware(MiddlewareA)
app.add_middleware(MiddlewareB)
```
Це призводить до такого порядку виконання:
* **Запит**: MiddlewareB → MiddlewareA → route
* **Відповідь**: route → MiddlewareA → MiddlewareB
Така поведінка стеку гарантує, що middleware виконуються у передбачуваному та керованому порядку.
## Інші middlewares { #other-middlewares }
Ви можете пізніше прочитати більше про інші middlewares в [Advanced User Guide: Advanced Middleware](../advanced/middleware.md){.internal-link target=_blank}.

View File

@@ -1,8 +1,8 @@
# Path Параметри та валідація числових даних
# Параметри шляху та валідація числових даних { #path-parameters-and-numeric-validations }
Так само як Ви можете оголошувати додаткові перевірки та метадані для query параметрів за допомогою `Query`, Ви можете оголошувати той самий тип перевірок і метаданих для параметрів шляху за допомогою `Path`.
Так само як ви можете оголошувати додаткові перевірки та метадані для query параметрів за допомогою `Query`, ви можете оголошувати той самий тип перевірок і метаданих для параметрів шляху за допомогою `Path`.
## Імпорт Path
## Імпорт `Path` { #import-path }
Спочатку імпортуйте `Path` з `fastapi` і імпортуйте `Annotated`:
@@ -10,70 +10,69 @@
/// info | Інформація
FastAPI додав підтримку `Annotated` (і почав рекомендувати його використання) у версії 0.95.0.
FastAPI додав підтримку `Annotated` (і почав рекомендувати його використання) у версії 0.95.0.
Якщо у Вас стара версія, при спробі використати `Annotated` можуть виникати помилки.
Якщо у вас стара версія, при спробі використати `Annotated` можуть виникати помилки.
Переконайтеся, що Ви [оновили версію FastAPI](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} принаймні до версії 0.95.1 перед використанням `Annotated`.
Переконайтеся, що ви [оновили версію FastAPI](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} принаймні до версії 0.95.1 перед використанням `Annotated`.
///
## Оголошення метаданих
## Оголошення метаданих { #declare-metadata }
Ви можете оголошувати всі ті ж параметри, що і для `Query`.
Наприклад, щоб оголосити значення метаданих `title` для параметра шляху `item_id`, Ви можете написати:
Наприклад, щоб оголосити значення метаданих `title` для параметра шляху `item_id`, ви можете написати:
{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[10] *}
/// note | Примітка
Параметр шляху завжди є обов’язковим, оскільки він має бути частиною шляху. Навіть якщо Ви оголосите його зі значенням `None` або встановите значення за замовчуванням — він все одно залишатиметься обов’язковим.
Параметр шляху завжди є обов’язковим, оскільки він має бути частиною шляху. Навіть якщо ви оголосите його зі значенням `None` або встановите значення за замовчуванням — це ні на що не вплине, він все одно завжди буде обов’язковим.
///
## Упорядковуйте параметри, як Вам потрібно
## Упорядковуйте параметри, як вам потрібно { #order-the-parameters-as-you-need }
/// tip | Підказка
/// tip | Порада
Це, мабуть, не настільки важливо або необхідно, якщо Ви використовуєте `Annotated`.
Це, мабуть, не настільки важливо або необхідно, якщо ви використовуєте `Annotated`.
///
Припустимо, Ви хочете оголосити параметр запиту `q` як обов’язковий `str`.
Припустимо, ви хочете оголосити параметр запиту `q` як обов’язковий `str`.
І Вам не потрібно оголошувати нічого іншого для цього параметра, тому немає потреби використовувати `Query`.
І вам не потрібно оголошувати нічого іншого для цього параметра, тому вам насправді не потрібно використовувати `Query`.
Але Вам все одно потрібно використовувати `Path` для параметра шляху `item_id`. І з певних причин Ви не хочете використовувати `Annotated`.
Але вам все одно потрібно використовувати `Path` для параметра шляху `item_id`. І з певних причин ви не хочете використовувати `Annotated`.
Python видасть помилку, якщо розмістити значення з "default" перед значенням, яке не має "default".
Але Ви можете змінити порядок і розмістити значення без значення за замовчуванням (параметр запиту `q`) першим.
Але ви можете змінити порядок і розмістити значення без значення за замовчуванням (параметр запиту `q`) першим.
Для **FastAPI** порядок не має значення. Він визначає параметри за їхніми іменами, типами та оголошеннями за замовчуванням (`Query`, `Path` тощо) і не звертає уваги на порядок.
Для **FastAPI** порядок не має значення. Він визначає параметри за їх іменами, типами та значеннями за замовчуванням (`Query`, `Path` тощо) і не звертає уваги на порядок.
Тому ви можете оголосити вашу функцію так:
Тому Ви можете оголосити Вашу функцію так:
{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *}
{* ../../docs_src/path_params_numeric_validations/tutorial002.py hl[7] *}
Але майте на увазі, що якщо Ви використовуєте `Annotated`, ця проблема не виникне, оскільки Ви не використовуєте значення за замовчуванням для параметрів `Query()` або `Path()`.
Але майте на увазі, що якщо ви використовуєте `Annotated`, цієї проблеми не буде, це не матиме значення, оскільки ви не використовуєте значення за замовчуванням параметрів функції для `Query()` або `Path()`.
{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *}
## Упорядковуйте параметри за потребою, хитрощі
## Упорядковуйте параметри, як вам потрібно: хитрощі { #order-the-parameters-as-you-need-tricks }
/// tip | Підказка
/// tip | Порада
Це, мабуть, не настільки важливо або необхідно, якщо Ви використовуєте `Annotated`.
Це, мабуть, не настільки важливо або необхідно, якщо ви використовуєте `Annotated`.
///
Ось **невелика хитрість**, яка може стати в пригоді, хоча вона рідко знадобиться.
Якщо Ви хочете:
Якщо ви хочете:
* оголосити параметр запиту `q` без використання `Query` або значення за замовчуванням
* оголосити параметр запиту `q` без `Query` і без жодного значення за замовчуванням
* оголосити параметр шляху `item_id`, використовуючи `Path`
* розмістити їх у різному порядку
* не використовувати `Annotated`
@@ -84,72 +83,72 @@ Python видасть помилку, якщо розмістити значен
Python нічого не зробить із цією `*`, але розпізнає, що всі наступні параметри слід викликати як аргументи за ключовим словом (пари ключ-значення), також відомі як <abbr title="From: K-ey W-ord Arg-uments"><code>kwargs</code></abbr>. Навіть якщо вони не мають значення за замовчуванням.
{* ../../docs_src/path_params_numeric_validations/tutorial003.py hl[7] *}
{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *}
### Краще з `Annotated`
### Краще з `Annotated` { #better-with-annotated }
Майте на увазі, якщо Ви використовуєте `Annotated`, оскільки Ви не використовуєте значення за замовчуванням для параметрів функції, цієї проблеми не виникне, і, швидше за все, Вам не потрібно буде використовувати `*`.
Майте на увазі, що якщо ви використовуєте `Annotated`, оскільки ви не використовуєте значення за замовчуванням параметрів функції, цієї проблеми не буде, і, ймовірно, вам не потрібно буде використовувати `*`.
{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *}
## Валідація числових даних: більше або дорівнює
## Валідація числових даних: більше або дорівнює { #number-validations-greater-than-or-equal }
За допомогою `Query` і `Path` (та інших, які Ви побачите пізніше) можна оголошувати числові обмеження.
За допомогою `Query` і `Path` (та інших, які ви побачите пізніше) можна оголошувати числові обмеження.
Тут, завдяки `ge=1`, `item_id` має бути цілим числом, яке "`g`reater than or `e`qual" (більше або дорівнює) `1`.
{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *}
## Валідація числових даних: більше ніж і менше або дорівнює
## Валідація числових даних: більше ніж і менше або дорівнює { #number-validations-greater-than-and-less-than-or-equal }
Те саме застосовується до:
* `gt`: `g`reater `t`han (більше ніж)
* `le`: `l`ess than or `e`qual (менше або дорівнює)
* `gt`: `g`reater `t`han
* `le`: `l`ess than or `e`qual
{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *}
## Валідація числових даних: float, більше ніж і менше ніж
## Валідація числових даних: float, більше ніж і менше ніж { #number-validations-floats-greater-than-and-less-than }
Валідація чисел також працює для значень типу `float`.
Ось де стає важливо мати можливість оголошувати <abbr title="greater than (більше ніж)"><code>gt</code></abbr>, а не тільки <abbr title="greater than or equal (більше або дорівнює)"><code>ge</code></abbr>. Це дозволяє, наприклад, вимагати, щоб значення було більше `0`, навіть якщо воно менше `1`.
Ось де стає важливо мати можливість оголошувати <abbr title="greater than"><code>gt</code></abbr>, а не тільки <abbr title="greater than or equal"><code>ge</code></abbr>. Це дозволяє, наприклад, вимагати, щоб значення було більше `0`, навіть якщо воно менше `1`.
Таким чином, значення `0.5` буде допустимим. Але `0.0` або `0` — ні.
Те саме стосується <abbr title="less than (менше ніж)"><code>lt</code></abbr>.
Те саме стосується <abbr title="less than"><code>lt</code></abbr>.
{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *}
## Підсумок
## Підсумок { #recap }
За допомогою `Query`, `Path` (і інших параметрів, які Ви ще не бачили) можна оголошувати метадані та перевірки рядків, так само як у [Query параметри та валідація рядків](query-params-str-validations.md){.internal-link target=_blank}.
За допомогою `Query`, `Path` (і інших параметрів, які ви ще не бачили) можна оголошувати метадані та перевірки рядків так само як у [Query параметри та валідація рядків](query-params-str-validations.md){.internal-link target=_blank}.
Також можна оголошувати числові перевірки:
* `gt`: `g`reater `t`han (більше ніж)
* `ge`: `g`reater than or `e`qual (більше або дорівнює)
* `lt`: `l`ess `t`han (менше ніж)
* `le`: `l`ess than or `e`qual (менше або дорівнює)
* `gt`: `g`reater `t`han
* `ge`: `g`reater than or `e`qual
* `lt`: `l`ess `t`han
* `le`: `l`ess than or `e`qual
/// info | Інформація
`Query`, `Path` та інші класи, які Ви побачите пізніше, є підкласами спільного класу `Param`.
`Query`, `Path` та інші класи, які ви побачите пізніше, є підкласами спільного класу `Param`.
Всі вони мають однакові параметри для додаткових перевірок і метаданих, які Ви вже бачили.
Всі вони мають однакові параметри для додаткових перевірок і метаданих, які ви вже бачили.
///
/// note | Технічні деталі
Коли Ви імпортуєте `Query`, `Path` та інші з `fastapi`, насправді це функції.
Коли ви імпортуєте `Query`, `Path` та інші з `fastapi`, насправді це функції.
При виклику вони повертають екземпляри класів з такими ж іменами.
Тобто Ви імпортуєте `Query`, яка є функцією. А коли Ви її викликаєте, вона повертає екземпляр класу, який теж називається `Query`.
Тобто ви імпортуєте `Query`, яка є функцією. А коли ви її викликаєте, вона повертає екземпляр класу, який теж називається `Query`.
Ці функції створені таким чином (замість використання класів напряму), щоб Ваш редактор не відзначав їхні типи як помилки.
Ці функції створені таким чином (замість використання класів напряму), щоб ваш редактор не відзначав їхні типи як помилки.
Таким чином, Ви можете користуватися своїм звичайним редактором і інструментами для програмування без додаткових налаштувань для ігнорування таких помилок.
Таким чином, ви можете користуватися своїм звичайним редактором і інструментами для програмування без додаткових налаштувань для ігнорування таких помилок.
///

View File

@@ -1,34 +1,34 @@
# Path Параметри
# Параметри шляху { #path-parameters }
Ви можете визначити "параметри" або "змінні" шляху, використовуючи синтаксис форматованих рядків:
Ви можете оголосити «параметри» або «змінні» шляху, використовуючи той самий синтаксис, що й у форматованих рядках Python:
{* ../../docs_src/path_params/tutorial001.py hl[6:7] *}
{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *}
Значення параметра шляху `item_id` передається у функцію як аргумент `item_id`.
Значення параметра шляху `item_id` буде передано у вашу функцію як аргумент `item_id`.
Якщо запустити цей приклад та перейти за посиланням <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>, то отримаємо таку відповідь:
Отже, якщо ви запустите цей приклад і перейдете за посиланням <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>, то побачите відповідь:
```JSON
{"item_id":"foo"}
```
## Path параметри з типами
## Параметри шляху з типами { #path-parameters-with-types }
Ви можете визначити тип параметра шляху у функції, використовуючи стандартні анотації типів Python:
Ви можете оголосити тип параметра шляху у функції, використовуючи стандартні анотації типів Python:
{* ../../docs_src/path_params/tutorial002.py hl[7] *}
{* ../../docs_src/path_params/tutorial002_py39.py hl[7] *}
У такому випадку `item_id` визначається як `int`.
У цьому випадку `item_id` оголошено як `int`.
/// check | Примітка
Це дасть можливість підтримки редактора всередині функції з перевірками помилок, автодоповнення тощо.
Це дасть вам підтримку редактора всередині функції з перевірками помилок, автодоповненням тощо.
///
## <abbr title="або: серіалізація, парсинг, маршалізація">Перетворення</abbr> даних
## <abbr title="also known as: serialization, parsing, marshalling також відомо як: серіалізація, парсинг, маршалізація">Перетворення</abbr> даних { #data-conversion }
Якщо запустити цей приклад і перейти за посиланням <a href="http://127.0.0.1:8000/items/3" class="external-link" target="_blank">http://127.0.0.1:8000/items/3</a>, то отримаєте таку відповідь:
Якщо ви запустите цей приклад і відкриєте у браузері <a href="http://127.0.0.1:8000/items/3" class="external-link" target="_blank">http://127.0.0.1:8000/items/3</a>, то побачите відповідь:
```JSON
{"item_id":3}
@@ -36,15 +36,15 @@
/// check | Примітка
Зверніть увагу, що значення, яке отримала (і повернула) ваша функція, — це `3`. Це Python `int`, а не рядок `"3"`.
Зверніть увагу, що значення, яке отримала (і повернула) ваша функція, — це `3`, як Python `int`, а не рядок `"3"`.
Отже, з таким оголошенням типу **FastAPI** автоматично виконує <abbr title="перетворення рядка, що надходить із HTTP-запиту, у типи даних Python">"парсинг"</abbr> запитів.
Отже, з таким оголошенням типу **FastAPI** надає вам автоматичний <abbr title="converting the string that comes from an HTTP request into Python data перетворення рядка, що надходить із HTTP-запиту, у дані Python">«parsing»</abbr> запиту.
///
## <abbr title="Або валідація">Перевірка</abbr> даних
## Валідація даних { #data-validation }
Якщо ж відкрити у браузері посилання <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>, то побачимо цікаву HTTP-помилку:
Але якщо ви перейдете у браузері за посиланням <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>, ви побачите гарну HTTP-помилку:
```JSON
{
@@ -61,144 +61,136 @@
]
}
```
тому що параметр шляху має значення `"foo"`, яке не є типом `int`.
Таку саму помилку отримаємо, якщо передати `float` замість `int`, як бачимо, у цьому прикладі: <a href="http://127.0.0.1:8000/items/4.2" class="external-link" target="_blank">http://127.0.0.1:8000/items/4.2</a>
тому що параметр шляху `item_id` мав значення `"foo"`, яке не є `int`.
Та сама помилка з’явиться, якщо ви передасте `float` замість `int`, як у: <a href="http://127.0.0.1:8000/items/4.2" class="external-link" target="_blank">http://127.0.0.1:8000/items/4.2</a>
/// check | Примітка
Отже, **FastAPI** надає перевірку типів з таким самим оголошенням типу в Python.
Отже, з тим самим оголошенням типу в Python **FastAPI** надає вам валідацію даних.
Зверніть увагу, що помилка також чітко вказує саме на те місце, де валідація не пройшла.
Зверніть увагу, що помилка також чітко вказує саме місце, де валідація не пройшла.
Це неймовірно корисно під час розробки та дебагінгу коду, що взаємодіє з вашим API.
Це неймовірно корисно під час розробки та налагодження коду, що взаємодіє з вашим API.
///
## Документація
## Документація { #documentation }
Тепер коли відкриєте свій браузер за посиланням <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>, то побачите автоматично згенеровану, інтерактивну API-документацію:
А коли ви відкриєте у браузері <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>, ви побачите автоматичну, інтерактивну, API-документацію на кшталт:
<img src="/img/tutorial/path-params/image01.png">
/// check | Примітка
Знову ж таки, лише з цим самим оголошенням типу в Python, FastAPI надає вам автоматичну, інтерактивну документацію (з інтеграцією Swagger UI).
Зверніть увагу, що параметр шляху оголошений як ціле число.
Знову ж таки, лише з тим самим оголошенням типу в Python **FastAPI** надає вам автоматичну, інтерактивну документацію (з інтеграцією Swagger UI).
Зверніть увагу, що параметр шляху оголошено як ціле число.
///
## Переваги стандартизації, альтернативна документація
## Переваги стандартів, альтернативна документація { #standards-based-benefits-alternative-documentation }
І оскільки згенерована схема відповідає стандарту <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md" class="external-link" target="_blank">OpenAPI</a>, існує багато сумісних інструментів.
З цієї причини FastAPI також надає альтернативну документацію API (використовуючи ReDoc), до якої можна отримати доступ за посиланням <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>:
Через це **FastAPI** також надає альтернативну API-документацію (використовуючи ReDoc), до якої ви можете отримати доступ за посиланням <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>:
<img src="/img/tutorial/path-params/image02.png">
Таким чином, існує багато сумісних інструментів, включаючи інструменти для генерації коду для багатьох мов.
Так само, існує багато сумісних інструментів. Зокрема інструменти генерації коду для багатьох мов.
## Pydantic { #pydantic }
## Pydantic
Уся валідація даних виконується за лаштунками за допомогою <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a>, тож ви отримуєте всі переваги від його використання. І ви знаєте, що ви в надійних руках.
Вся валідація даних виконується за лаштунками за допомогою <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a>, тому Ви отримуєте всі переваги від його використання. І можете бути впевнені, що все в надійних руках.
Ви можете використовувати ті самі оголошення типів з `str`, `float`, `bool` та багатьма іншими складними типами даних.
Ви можете використовувати ті самі оголошення типів з `str`, `float`, `bool` та багатьма іншими складними типами даних.
Декілька з них розглядаються в наступних розділах посібника.
Декілька з них будуть розглянуті в наступних розділах посібника.
## Порядок має значення { #order-matters }
## Порядок має значення
Під час створення *операцій шляху* можуть виникати ситуації, коли у вас є фіксований шлях.
При створенні *операцій шляху* можуть виникати ситуації, коли шлях фіксований.
Наприклад, `/users/me` — припустімо, це для отримання даних про поточного користувача.
Наприклад, `/users/me`. Припустимо, що це шлях для отримання даних про поточного користувача.
І тоді у вас також може бути шлях `/users/{user_id}` для отримання даних про конкретного користувача за його ID.
А також у вас може бути шлях `/users/{user_id}`, щоб отримати дані про конкретного користувача за його ID.
Оскільки *операції шляху* оцінюються по черзі, вам потрібно переконатися, що шлях для `/users/me` оголошено перед шляхом для `/users/{user_id}`:
Оскільки *операції шляху* оцінюються по черзі, Ви повинні переконатися, що шлях для `/users/me` оголошений перед шляхом для `/users/{user_id}`:
{* ../../docs_src/path_params/tutorial003_py39.py hl[6,11] *}
{* ../../docs_src/path_params/tutorial003.py hl[6,11] *}
Інакше шлях для `/users/{user_id}` також відповідатиме `/users/me`, «вважаючи», що отримує параметр `user_id` зі значенням `"me"`.
Інакше шлях для `/users/{user_id}` також буде відповідати для `/users/me`, "вважаючи", що він отримує параметр `user_id` зі значенням `"me"`.
Так само ви не можете перевизначити операцію шляху:
Аналогічно, Ви не можете оголосити операцію шляху:
{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *}
{* ../../docs_src/path_params/tutorial003b.py hl[6,11] *}
Завжди використовуватиметься перша, оскільки шлях збігається першим.
Перша операція буде завжди використовуватися, оскільки шлях збігається першим.
## Попередньо визначені значення
## Попередньо визначені значення { #predefined-values }
Якщо у вас є *операція шляху*, яка приймає *параметр шляху*, але Ви хочете, щоб можливі допустимі значення *параметра шляху* були попередньо визначені, Ви можете використати стандартний Python <abbr title="перелічення">Enum</abbr>.
Якщо у вас є *операція шляху*, яка отримує *параметр шляху*, але ви хочете, щоб можливі коректні значення *параметра шляху* були попередньо визначені, ви можете використати стандартний Python <abbr title="Enumeration">`Enum`</abbr>.
### Створення класу `Enum`
### Створіть клас `Enum` { #create-an-enum-class }
Імпортуйте `Enum` і створіть підклас, що наслідується від `str` та `Enum`.
Наслідуючи від `str`, документація API зможе визначити, що значення повинні бути типу `string`, і правильно їх відобразить.
Завдяки наслідуванню від `str` документація API зможе визначити, що значення повинні бути типу `string`, і зможе коректно їх відобразити.
Після цього створіть атрибути класу з фіксованими значеннями, які будуть доступними допустимими значеннями:
Після цього створіть атрибути класу з фіксованими значеннями, які будуть доступними коректними значеннями:
{* ../../docs_src/path_params/tutorial005.py hl[1,6:9] *}
/// info | Додаткова інформація
<a href="https://docs.python.org/3/library/enum.html" class="external-link" target="_blank">Перелічення (або enums) доступні в Python</a> починаючи з версії 3.4.
///
{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *}
/// tip | Порада
Якщо вам цікаво, "AlexNet", "ResNet" та "LeNet" — це просто назви ML моделей <abbr title="Технічно, архітектури Deep Learning моделей">Machine Learning</abbr>.
Якщо вам цікаво, «AlexNet», «ResNet» та «LeNet» — це просто назви Machine Learning <abbr title="Technically, Deep Learning model architectures технічно, архітектури моделей Deep Learning">models</abbr>.
///
### Оголосіть *параметр шляху*
### Оголосіть *параметр шляху* { #declare-a-path-parameter }
Потім створіть *параметр шляху* з анотацією типу, використовуючи створений вами клас enum (`ModelName`):
{* ../../docs_src/path_params/tutorial005.py hl[16] *}
{* ../../docs_src/path_params/tutorial005_py39.py hl[16] *}
### Перевірка документації
### Перевірте документацію { #check-the-docs }
Оскільки доступні значення для *параметра шляху* визначені заздалегідь, інтерактивна документація зможе красиво їх відобразити:
Оскільки доступні значення для *параметра шляху* визначені заздалегідь, інтерактивна документація може красиво їх показати:
<img src="/img/tutorial/path-params/image03.png">
### Робота з *перелічуваннями* у Python
### Робота з Python *переліченнями* { #working-with-python-enumerations }
Значення *параметра шляху* буде елементом *перелічування*.
Значення *параметра шляху* буде *елементом перелічування*.
#### Порівняння *елементів перелічування*
#### Порівняйте *елементи перелічування* { #compare-enumeration-members }
Ви можете порівнювати його з *елементами перелічування* у створеному вами enum `ModelName`:
Ви можете порівнювати його з *елементом перелічування* у створеному вами enum `ModelName`:
{* ../../docs_src/path_params/tutorial005.py hl[17] *}
{* ../../docs_src/path_params/tutorial005_py39.py hl[17] *}
#### Отримання *значення перелічування*
#### Отримайте *значення перелічування* { #get-the-enumeration-value }
Ви можете отримати фактичне значення (у цьому випадку це `str`), використовуючи `model_name.value`, або загалом `your_enum_member.value`:
{* ../../docs_src/path_params/tutorial005.py hl[20] *}
{* ../../docs_src/path_params/tutorial005_py39.py hl[20] *}
/// tip | Порада
Ви також можете отримати доступ до значення `"lenet"`, використовуючи `ModelName.lenet.value`.
Ви також можете отримати доступ до значення `"lenet"` через `ModelName.lenet.value`.
///
#### Поверніть *елементи перелічування* { #return-enumeration-members }
#### Повернення *елементів перелічування*
Ви можете повертати *елементи перелічування* з вашої *операції шляху*, навіть вкладені у JSON-тіло (наприклад, `dict`).
Ви можете повертати *елементи enum* з вашої *операції шляху*, навіть вкладені у JSON-тіло (наприклад, `dict`).
Вони будуть перетворені на відповідні значення (у цьому випадку рядки) перед поверненням клієнту:
{* ../../docs_src/path_params/tutorial005.py hl[18,21,23] *}
{* ../../docs_src/path_params/tutorial005_py39.py hl[18,21,23] *}
На стороні клієнта Ви отримаєте відповідь у форматі JSON, наприклад:
На стороні клієнта ви отримаєте відповідь у форматі JSON, наприклад:
```JSON
{
@@ -207,36 +199,35 @@
}
```
## Path-параметри, що містять шляхи
## Параметри шляху, що містять шляхи { #path-parameters-containing-paths }
Припустимо, у вас є *операція шляху* з маршрутом `/files/{file_path}`.
Припустімо, у вас є *операція шляху* зі шляхом `/files/{file_path}`.
Але вам потрібно, щоб `file_path` містив *шлях*, наприклад `home/johndoe/myfile.txt`.
Але вам потрібно, щоб `file_path` сам містив *шлях*, наприклад `home/johndoe/myfile.txt`.
Отже, URL для цього файлу виглядатиме так: `/files/home/johndoe/myfile.txt`.
Отже, URL для цього файлу виглядатиме приблизно так: `/files/home/johndoe/myfile.txt`.
### Підтримка OpenAPI { #openapi-support }
OpenAPI не підтримує спосіб оголошення *параметра шляху*, який має містити всередині *шлях*, оскільки це може призвести до сценаріїв, які складно тестувати та визначати.
### Підтримка OpenAPI
Проте ви все одно можете зробити це в **FastAPI**, використовуючи один із внутрішніх інструментів Starlette.
OpenAPI не підтримує спосіб оголошення *параметра шляху*, що містить *шлях* всередині, оскільки це може призвести до сценаріїв, які складно тестувати та визначати.
І документація все ще працюватиме, хоча й не додаватиме жодної документації, яка б казала, що параметр має містити шлях.
Однак (одначе), Ви все одно можете зробити це в **FastAPI**, використовуючи один із внутрішніх інструментів Starlette.
### Конвертер шляху { #path-convertor }
Документація все ще працюватиме, хоча й не додаватиме опису про те, що параметр повинен містити шлях.
### Конвертер шляху
Використовуючи опцію безпосередньо зі Starlette, Ви можете оголосити *параметр шляху*, що містить *шлях*, використовуючи URL на кшталт:
Використовуючи опцію безпосередньо зі Starlette, ви можете оголосити *параметр шляху*, що містить *шлях*, використовуючи URL на кшталт:
```
/files/{file_path:path}
```
У цьому випадку ім'я параметра — `file_path`, а остання частина `:path` вказує на те, що параметр повинен відповідати будь-якому *шляху*.
Отже, Ви можете використати його так:
У цьому випадку ім’я параметра — `file_path`, а остання частина `:path` вказує, що параметр має відповідати будь-якому *шляху*.
{* ../../docs_src/path_params/tutorial004.py hl[6] *}
Отже, ви можете використати його так:
{* ../../docs_src/path_params/tutorial004_py39.py hl[6] *}
/// tip | Порада
@@ -246,15 +237,15 @@ OpenAPI не підтримує спосіб оголошення *параме
///
## Підсумок
## Підсумок { #recap }
З **FastAPI**, використовуючи короткі, інтуїтивно зрозумілі та стандартні оголошення типів Python, Ви отримуєте:
З **FastAPI**, використовуючи короткі, інтуїтивно зрозумілі та стандартні оголошення типів Python, ви отримуєте:
* Підтримку в редакторі: перевірка помилок, автодоповнення тощо.
* "<abbr title="перетворення рядка, що надходить з HTTP-запиту, у типи даних Python">Парсинг</abbr>" даних
* Підтримку редактора: перевірка помилок, автодоповнення тощо.
* Перетворення даних «<abbr title="converting the string that comes from an HTTP request into Python data перетворення рядка, що надходить з HTTP-запиту, у дані Python">parsing</abbr>»
* Валідацію даних
* Анотацію API та автоматичну документацію
І вам потрібно оголосити їх лише один раз.
Це, ймовірно, основна видима перевага **FastAPI** порівняно з альтернативними фреймворками (окрім високої продуктивності).
Це, ймовірно, основна видима перевага **FastAPI** порівняно з альтернативними фреймворками (окрім сирої продуктивності).

View File

@@ -1,4 +1,4 @@
# Моделі Query параметрів
# Моделі параметрів запиту { #query-parameter-models }
Якщо у Вас є група **query параметрів**, які пов’язані між собою, Ви можете створити **Pydantic-модель** для їх оголошення.
@@ -10,7 +10,7 @@
///
## Query параметри з Pydantic-моделлю
## Query параметри з Pydantic-моделлю { #query-parameters-with-a-pydantic-model }
Оголосіть **query параметри**, які Вам потрібні, у **Pydantic-моделі**, а потім оголосіть цей параметр як `Query`:
@@ -18,7 +18,7 @@
**FastAPI** буде **витягувати** дані для **кожного поля** з **query параметрів** у запиті та передавати їх у визначену вами Pydantic-модель.
## Перевірте документацію
## Перевірте документацію { #check-the-docs }
Ви можете побачити параметри запиту в UI документації за `/docs`:
@@ -26,7 +26,7 @@
<img src="/img/tutorial/query-param-models/image01.png">
</div>
## Заборона зайвих Query параметрів
## Заборона зайвих Query параметрів { #forbid-extra-query-parameters }
У деяких особливих випадках (ймовірно, не дуже поширених) Ви можете захотіти **обмежити** query параметри, які дозволено отримувати.
@@ -34,7 +34,7 @@
{* ../../docs_src/query_param_models/tutorial002_an_py310.py hl[10] *}
Якщо клієнт спробує надіслати **зайві** дані у **query параметрах**, він отримає **помилку**.
Якщо клієнт спробує надіслати **зайві** дані у **query параметрах**, він отримає **помилку** відповідь.
Наприклад, якщо клієнт спробує надіслати query параметр `tool` зі значенням `plumbus`, як у цьому запиті:
@@ -57,11 +57,11 @@ https://example.com/items/?limit=10&tool=plumbus
}
```
## Підсумок
## Підсумок { #summary }
Ви можете використовувати **Pydantic-моделі** для оголошення **query параметрів** у **FastAPI**. 😎
/// tip | Підказка
/// tip | Порада
Спойлер: Ви також можете використовувати Pydantic-моделі для оголошення cookie та заголовків, але про це Ви дізнаєтеся пізніше в цьому посібнику. 🤫

View File

@@ -1,26 +1,26 @@
# Query параметри та валідація рядків
# Query параметри та валідація рядків { #query-parameters-and-string-validations }
**FastAPI** дозволяє оголошувати додаткову інформацію та виконувати валідацію для Ваших параметрів.
**FastAPI** дозволяє оголошувати додаткову інформацію та виконувати валідацію для ваших параметрів.
Розглянемо цей додаток як приклад:
{* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *}
Query параметр `q` має тип `str | None`, що означає, що він може бути як `str`, так і `None`. За замовчуванням він має значення `None`, тому FastAPI розуміє, що цей параметр не є обов'язковим.
Query параметр `q` має тип `str | None`, що означає, що він має тип `str`, але також може бути `None`, і справді, значення за замовчуванням — `None`, тож FastAPI знатиме, що він не є обов'язковим.
/// note | Примітка
FastAPI знає, що `q` не є обов’язковим, завдяки значенню за замовчуванням `= None`.
FastAPI знатиме, що значення `q` не є обов’язковим, завдяки значенню за замовчуванням `= None`.
Використання `str | None` дозволить Вашому редактору коду надавати кращу підтримку та виявляти помилки.
Використання `str | None` дозволить вашому редактору коду надавати кращу підтримку та виявляти помилки.
///
## Додаткова валідація
## Додаткова валідація { #additional-validation }
Ми хочемо, щоб навіть якщо `q` є необов’язковим, **його довжина не перевищувала 50 символів**, якщо він все ж буде переданий.
Ми хочемо, щоб навіть якщо `q` є необов’язковим, коли його передають, **його довжина не перевищувала 50 символів**.
### Імпорт `Query` та `Annotated`
### Імпорт `Query` та `Annotated` { #import-query-and-annotated }
Щоб це зробити, спочатку імпортуємо:
@@ -33,13 +33,13 @@ FastAPI знає, що `q` не є обов’язковим, завдяки з
FastAPI додав підтримку `Annotated` (і почав рекомендувати його) у версії 0.95.0.
Якщо у Вас старіша версія, під час використання `Annotated` можуть виникати помилки.
Якщо у вас старіша версія, під час використання `Annotated` можуть виникати помилки.
Переконайтеся, що Ви [оновили версію FastAPI](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} до принаймні 0.95.1, перш ніж використовувати `Annotated`.
Переконайтеся, що ви [оновили версію FastAPI](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} до принаймні 0.95.1, перш ніж використовувати `Annotated`.
///
## Використання `Annotated` у типі параметра `q`
## Використання `Annotated` у типі параметра `q` { #use-annotated-in-the-type-for-the-q-parameter }
Пам’ятаєте, як я раніше розповідав, що `Annotated` можна використовувати для додавання метаданих до параметрів у [Вступі до типів Python](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank}?
@@ -55,7 +55,7 @@ q: str | None = None
////
//// tab | Python 3.8+
//// tab | Python 3.9+
```Python
q: Union[str, None] = None
@@ -73,7 +73,7 @@ q: Annotated[str | None] = None
////
//// tab | Python 3.8+
//// tab | Python 3.9+
```Python
q: Annotated[Union[str, None]] = None
@@ -85,33 +85,33 @@ q: Annotated[Union[str, None]] = None
А тепер переходимо до цікавого! 🎉
## Додавання `Query` до `Annotated` у параметр `q`
## Додавання `Query` до `Annotated` у параметр `q` { #add-query-to-annotated-in-the-q-parameter }
Тепер, коли у нас є `Annotated`, де ми можемо додавати додаткову інформацію (зокрема валідацію), додамо `Query` всередину `Annotated` і встановимо параметр `max_length` у `50`:
Тепер, коли у нас є `Annotated`, де ми можемо додавати додаткову інформацію (у цьому випадку — додаткову валідацію), додамо `Query` всередину `Annotated` і встановимо параметр `max_length` у `50`:
{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[9] *}
Зверніть увагу, що значення за замовчуванням усе ще `None`, тому параметр залишається необов'язковим.
Але тепер, додавши `Query(max_length=50)` всередину `Annotated`, ми повідомляємо FastAPI, що хочемо **додаткову валідацію** для цього значення — воно має містити максимум 50 символів. 😎
Але тепер, додавши `Query(max_length=50)` всередину `Annotated`, ми повідомляємо FastAPI, що хочемо **додаткову валідацію** для цього значення: ми хочемо, щоб воно мало максимум 50 символів. 😎
/// tip | Підказка
/// tip | Порада
Ми використовуємо `Query()`, оскільки це **query параметр**. Далі ми розглянемо інші варіанти, як-от `Path()`, `Body()`, `Header()` та `Cookie()`, які приймають ті самі аргументи, що й `Query()`.
Тут ми використовуємо `Query()`, оскільки це **query параметр**. Далі ми розглянемо інші варіанти, як-от `Path()`, `Body()`, `Header()` та `Cookie()`, які приймають ті самі аргументи, що й `Query()`.
///
Тепер FastAPI:
* **Перевірить** дані, щоб переконатися, що їхня довжина не перевищує 50 символів
* **Перевірить** дані, щоб переконатися, що їхня максимальна довжина — 50 символів
* Покажe **чітку помилку** клієнту, якщо дані недійсні
* **Задокументує** параметр в OpenAPI-схемі *операції шляху* (що відобразиться в **автоматично згенерованій документації**)
## Альтернативний (застарілий) метод: Query як значення за замовчуванням
## Альтернативний (застарілий) метод: `Query` як значення за замовчуванням { #alternative-old-query-as-the-default-value }
У попередніх версіях FastAPI (до <abbr title="до 2023-03">0.95.0</abbr>) `Query` використовувався як значення за замовчуванням для параметра, а не всередині `Annotated`. Ви, ймовірно, побачите код, який використовує цей підхід, тому варто розглянути його.
У попередніх версіях FastAPI (до <abbr title="before 2023-03 до 2023-03">0.95.0</abbr>) потрібно було використовувати `Query` як значення за замовчуванням параметра, замість того, щоб додавати його в `Annotated`. Є висока ймовірність, що ви зустрінете код із таким підходом, тож я поясню його.
/// tip | Підказка
/// tip | Порада
Для нового коду та коли це можливо, використовуйте `Annotated`, як показано вище. Це має багато переваг (пояснених нижче) і не має недоліків. 🍰
@@ -121,7 +121,7 @@ q: Annotated[Union[str, None]] = None
{* ../../docs_src/query_params_str_validations/tutorial002_py310.py hl[7] *}
Оскільки в цьому випадку (без `Annotated`) нам потрібно замінити `None` у функції на `Query()`, тепер ми повинні явно встановити значення за замовчуванням через параметр `Query(default=None)`. Це виконує ту саму роль визначення значення за замовчуванням (принаймні для FastAPI).
Оскільки в цьому випадку (без `Annotated`) нам потрібно замінити значення за замовчуванням `None` у функції на `Query()`, тепер ми повинні встановити значення за замовчуванням через параметр `Query(default=None)`. Це виконує ту саму роль визначення значення за замовчуванням (принаймні для FastAPI).
Таким чином:
@@ -135,9 +135,10 @@ q: str | None = Query(default=None)
```Python
q: str | None = None
```
Але у версії з `Query` ми явно вказуємо, що це query параметр.
Далі ми можемо передавати `Query` додаткові параметри, зокрема `max_length`, який застосовується до рядків:
Але у версії з `Query` ми явно вказуємо, що це query параметр.
Далі ми можемо передавати `Query` додаткові параметри. У цьому випадку — параметр `max_length`, який застосовується до рядків:
```Python
q: str | None = Query(default=None, max_length=50)
@@ -145,11 +146,11 @@ q: str | None = Query(default=None, max_length=50)
Це забезпечить валідацію даних, виведе зрозумілу помилку у разі недійсних даних і задокументує параметр у схемі OpenAPI *операції шляху*.
### `Query` як значення за замовчуванням або всередині `Annotated`
### `Query` як значення за замовчуванням або всередині `Annotated` { #query-as-the-default-value-or-in-annotated }
Важливо пам’ятати, якщо використовувати `Query` всередині `Annotated`, не можна задавати параметр `default` у `Query`.
Замість цього використовуйте значення за замовчуванням у самій функції. Інакше це буде нелогічно.
Замість цього використовуйте фактичне значення за замовчуванням параметра функції. Інакше це буде непослідовно.
Наприклад, цей варіант є некоректним:
@@ -159,39 +160,39 @@ q: Annotated[str, Query(default="rick")] = "morty"
...тому, що не зрозуміло, яке значення має бути значенням за замовчуванням: `"rick"` чи `"morty"`.
Коректні варіанти:
Тож ви будете використовувати (бажано):
```Python
q: Annotated[str, Query()] = "rick"
```
...або у старих кодових базах Ви знайдете:
...або у старих кодових базах ви знайдете:
```Python
q: str = Query(default="rick")
```
### Переваги використання `Annotated`
### Переваги використання `Annotated` { #advantages-of-annotated }
**Використання `Annotated` є рекомендованим** замість задання значення за замовчуванням у параметрах функції, оскільки воно **краще** з кількох причин. 🤓
Значення **за замовчуванням** параметра **функції** є його **фактичним значенням за замовчуванням**, що є більш інтуїтивним у Python загалом. 😌
Значення **за замовчуванням** параметра **функції** є **фактичним значенням за замовчуванням**, що є більш інтуїтивним у Python загалом. 😌
Ви можете **викликати** ту саму функцію **в інших місцях** без FastAPI, і вона **працюватиме очікувано**. Якщо параметр є **обов’язковим** (без значення за замовчуванням), Ваш **редактор** повідомить про помилку, а **Python** також видасть помилку, якщо Ви виконаєте функцію без передавання цього параметра.
Ви можете **викликати** ту саму функцію **в інших місцях** без FastAPI, і вона **працюватиме очікувано**. Якщо параметр є **обов’язковим** (без значення за замовчуванням), ваш **редактор** повідомить про помилку, а **Python** також видасть помилку, якщо ви виконаєте функцію без передавання цього параметра.
Якщо Ви не використовуєте `Annotated`, а використовуєте **(старий) стиль значень за замовчуванням**, то при виклику цієї функції без FastAPI **в інших місцях**, потрібно **не забути** передати їй аргументи, інакше значення будуть відрізнятися від очікуваних (наприклад, Ви отримаєте `QueryInfo` або подібне замість `str`). Ваш редактор не повідомить про помилку, і Python також не видасть помилку при запуску функції, поки не виникне помилка під час виконання операцій усередині.
Якщо ви не використовуєте `Annotated`, а використовуєте **(старий) стиль значень за замовчуванням**, то при виклику цієї функції без FastAPI **в інших місцях**, потрібно **пам’ятати** передати їй аргументи, щоб вона працювала коректно, інакше значення будуть відрізнятися від очікуваних (наприклад, ви отримаєте `QueryInfo` або щось подібне замість `str`). І ваш редактор не повідомить про помилку, і Python не скаржитиметься під час запуску цієї функції — лише коли операції всередині завершаться помилкою.
Оскільки `Annotated` може містити кілька анотацій метаданих, Ви навіть можете використовувати ту саму функцію з іншими інструментами, такими як <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">Typer</a>. 🚀
Оскільки `Annotated` може містити кілька анотацій метаданих, тепер ви навіть можете використовувати ту саму функцію з іншими інструментами, такими як <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">Typer</a>. 🚀
## Додавання додаткових валідацій
## Додавання додаткових валідацій { #add-more-validations }
Ви також можете додати параметр `min_length`:
{* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *}
## Додавання регулярних виразів
## Додавання регулярних виразів { #add-regular-expressions }
Ви можете визначити <abbr title="Регулярний вираз (regex або regexp) — це послідовність символів, яка визначає шаблон для пошуку в рядках.">регулярний вираз</abbr> pattern, якому має відповідати параметр:
Ви можете визначити <abbr title="A regular expression, regex or regexp is a sequence of characters that define a search pattern for strings. Регулярний вираз (regex або regexp) — це послідовність символів, яка визначає шаблон для пошуку в рядках.">regular expression</abbr> `pattern`, якому має відповідати параметр:
{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *}
@@ -201,41 +202,27 @@ q: str = Query(default="rick")
* `fixedquery`: точно відповідає значенню `fixedquery`.
* `$`: закінчується тут, після `fixedquery` немає жодних символів.
Якщо Ви почуваєтеся розгублено щодо **"регулярних виразів"**, не хвилюйтеся. Вони є складною темою для багатьох людей. Ви все одно можете зробити багато речей без їх використання.
Якщо ви почуваєтеся розгублено щодо **«regular expression»**, не хвилюйтеся. Це складна тема для багатьох людей. Ви все одно можете робити багато речей без використання регулярних виразів.
Але тепер Ви знаєте, що коли вони знадобляться, їх можна застосовувати у **FastAPI**.
Тепер ви знаєте, що коли вони знадобляться, їх можна застосовувати у **FastAPI**.
### Pydantic v1 `regex` замість `pattern`
## Значення за замовчуванням { #default-values }
До версії Pydantic 2 і FastAPI 0.100.0 параметр називався `regex` замість `pattern`, але тепер він застарів.
Ви можете, звісно, використовувати значення за замовчуванням, відмінні від `None`.
Ви все ще можете зустріти код, який використовує його:
//// tab | Pydantic v1
{* ../../docs_src/query_params_str_validations/tutorial004_regex_an_py310.py hl[11] *}
////
Але майте на увазі, що він є застарілим і його слід оновити до нового параметра `pattern`. 🤓
## Значення за замовчуванням
Ви можете використовувати значення за замовчуванням, відмінні від `None`.
Наприклад, якщо Ви хочете оголосити параметр запиту `q` з `min_length` `3` і значенням за замовчуванням `"fixedquery"`:
Припустімо, що ви хочете оголосити query параметр `q` з `min_length` `3` і значенням за замовчуванням `"fixedquery"`:
{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *}
/// note | Технічні деталі
/// note | Примітка
Наявність значення за замовчуванням будь-якого типу, включаючи `None`, робить параметр необов’язковим (not required).
///
## Обов’язкові параметри
## Обов’язкові параметри { #required-parameters }
Якщо нам не потрібно вказувати додаткові перевірки або метадані, ми можемо зробити параметр `q` обов’язковим, просто не оголошуючи значення за замовчуванням, наприклад:
Якщо нам не потрібно оголошувати додаткові валідації або метадані, ми можемо зробити query параметр `q` обов’язковим, просто не вказуючи значення за замовчуванням, наприклад:
```Python
q: str
@@ -247,43 +234,39 @@ q: str
q: str | None = None
```
Але тепер ми оголошуємо його з `Query`, наприклад:
//// tab | Annotated
Але тепер ми оголошуємо його з `Query`, наприклад так:
```Python
q: Annotated[str | None, Query(min_length=3)] = None
```
////
Тому, якщо Вам потрібно зробити значення обов’язковим, використовуючи `Query`, просто не вказуйте значення за замовчуванням:
Тому, якщо вам потрібно оголосити значення як обов’язкове під час використання `Query`, просто не вказуйте значення за замовчуванням:
{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *}
### Обов’язкове значення, яке може бути `None`
### Обов’язковий, може бути `None` { #required-can-be-none }
Ви можете вказати, що параметр може приймати `None`, але при цьому залишається обов’язковим. Це змусить клієнтів надіслати значення, навіть якщо воно дорівнює `None`.
Ви можете вказати, що параметр може приймати `None`, але при цьому залишається обов’язковим. Це змусить клієнтів надіслати значення, навіть якщо значення дорівнює `None`.
Щоб зробити це, оголосіть, що `None` є допустимим типом, але не вказуйте значення за замовчуванням:
Щоб зробити це, оголосіть, що `None` є допустимим типом, але просто не вказуйте значення за замовчуванням:
{* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *}
## Список параметрів запиту / кілька значень
## Список query параметрів / кілька значень { #query-parameter-list-multiple-values }
Якщо Ви визначаєте параметр запиту за допомогою `Query`, Ви також можете дозволити отримання списку значень, тобто дозволити отримання кількох значень.
Коли ви явно визначаєте query параметр за допомогою `Query`, ви також можете оголосити, що він має приймати список значень, або, іншими словами, кілька значень.
Наприклад, щоб дозволити параметру запиту `q` з'являтися кілька разів в URL, можна написати:
Наприклад, щоб оголосити query параметр `q`, який може зявлятися в URL кілька разів, можна написати:
{* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *}
Тоді, у випадку запиту за URL:
Тоді, у випадку URL:
```
http://localhost:8000/items/?q=foo&q=bar
```
Ви отримаєте кілька значень *query параметра* `q` (`foo` і `bar`) у вигляді списку `list` в Python у Вашій *функції обробки шляху*, у *параметрі функції* `q`.
ви отримаєте кілька значень `q` *query параметрів* (`foo` і `bar`) у вигляді Python `list` у вашій *функції операції шляху*, у *параметрі функції* `q`.
Отже, відповідь на цей URL буде:
@@ -296,9 +279,9 @@ http://localhost:8000/items/?q=foo&q=bar
}
```
/// tip | Підказка
/// tip | Порада
Щоб оголосити параметр запиту з типом `list`, як у наведеному вище прикладі, потрібно явно використовувати `Query`, інакше він буде інтерпретований як тіло запиту.
Щоб оголосити query параметр з типом `list`, як у наведеному вище прикладі, потрібно явно використовувати `Query`, інакше він буде інтерпретований як тіло запиту.
///
@@ -306,19 +289,19 @@ http://localhost:8000/items/?q=foo&q=bar
<img src="/img/tutorial/query-params-str-validations/image02.png">
### Список параметрів запиту / кілька значень за замовчуванням
### Список query параметрів / кілька значень за замовчуванням { #query-parameter-list-multiple-values-with-defaults }
Ви також можете визначити значення за замовчуванням для `list`, якщо жодне значення не було передане:
Ви також можете визначити значення за замовчуванням `list`, якщо жодне значення не було передане:
{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *}
Якщо Ви перейдете за посиланням:
Якщо ви перейдете за посиланням:
```
http://localhost:8000/items/
```
то значення `q` за замовчуванням буде: `["foo", "bar"]`, і Ваша відповідь виглядатиме так:
то значення `q` за замовчуванням буде: `["foo", "bar"]`, і ваша відповідь виглядатиме так:
```JSON
{
@@ -329,35 +312,35 @@ http://localhost:8000/items/
}
```
#### Використання тільки `list`
#### Використання тільки `list` { #using-just-list }
Ви також можете використовувати `list` без уточнення типу, замість `list[str]`:
Ви також можете використовувати `list` напряму замість `list[str]`:
{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *}
/// note | Технічні деталі
/// note | Примітка
Майте на увазі, що в цьому випадку FastAPI не перевірятиме вміст списку.
Наприклад, `list[int]` перевірятиме (і документуватиме), що всі елементи списку є цілими числами. Але `list` без уточнення цього не робитиме.
Наприклад, `list[int]` перевірятиме (і документуватиме), що вміст списку цілі числа. Але `list` без уточнення цього не робитиме.
///
## Додавання додаткових метаданих
## Оголосити більше метаданих { #declare-more-metadata }
Ви можете додати більше інформації про параметр.
Ця інформація буде включена у згенерований OpenAPI та використана в інтерфейсах документації та зовнішніх інструментах.
Ця інформація буде включена у згенерований OpenAPI та використана інтерфейсами документації та зовнішніми інструментами.
/// note | Технічні деталі
/// note | Примітка
Майте на увазі, що різні інструменти можуть мати різний рівень підтримки OpenAPI.
Деякі з них можуть ще не відображати всю додаткову інформацію, хоча в більшості випадків ця функція вже запланована для розробки.
Деякі з них можуть ще не відображати всю додаткову інформацію, хоча в більшості випадків відсутню функцію вже заплановано до реалізації.
///
Ви можете додати `title` :
Ви можете додати `title`:
{* ../../docs_src/query_params_str_validations/tutorial007_an_py310.py hl[10] *}
@@ -365,9 +348,9 @@ http://localhost:8000/items/
{* ../../docs_src/query_params_str_validations/tutorial008_an_py310.py hl[14] *}
## Аліаси параметрів
## Аліаси параметрів { #alias-parameters }
Уявіть, що Ви хочете, щоб параметр називався `item-query`.
Уявіть, що ви хочете, щоб параметр називався `item-query`.
Наприклад:
@@ -379,19 +362,19 @@ http://127.0.0.1:8000/items/?item-query=foobaritems
Найближчий допустимий варіант — `item_query`.
Проте Вам потрібно, щоб параметр залишався саме `item-query`...
Проте вам потрібно, щоб параметр залишався саме `item-query`...
У такому випадку можна оголосити `alias`, і саме він буде використовуватися для отримання значення параметра:
{* ../../docs_src/query_params_str_validations/tutorial009_an_py310.py hl[9] *}
## Виведення параметрів як застарілих
## Позначення параметрів як застарілих { #deprecating-parameters }
Припустимо, що Ви більше не хочете використовувати цей параметр.
Припустімо, що вам більше не подобається цей параметр.
Вам потрібно залишити його на деякий час, оскільки ним користуються клієнти, але Ви хочете, щоб документація чітко показувала, що він є <abbr title="застарілий, не рекомендується до використання">застарілим</abbr>.
Вам потрібно залишити його на деякий час, оскільки ним користуються клієнти, але ви хочете, щоб документація чітко показувала, що він є <abbr title="obsolete, recommended not to use it застарілий, не рекомендується до використання">deprecated</abbr>.
Тоді Ви можете передати параметр `deprecated=True` до `Query`:
Тоді передайте параметр `deprecated=True` до `Query`:
{* ../../docs_src/query_params_str_validations/tutorial010_an_py310.py hl[19] *}
@@ -399,27 +382,27 @@ http://127.0.0.1:8000/items/?item-query=foobaritems
<img src="/img/tutorial/query-params-str-validations/image01.png">
## Виняток параметрів з OpenAPI
## Виняток параметрів з OpenAPI { #exclude-parameters-from-openapi }
Щоб виключити параметр запиту зі згенерованої схеми OpenAPI (і, таким чином, з автоматичних систем документації), встановіть параметр `include_in_schema` для `Query` в `False`:
Щоб виключити query параметр зі згенерованої схеми OpenAPI (і, таким чином, з автоматичних систем документації), встановіть параметр `include_in_schema` для `Query` в `False`:
{* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *}
## Кастомна валідація
## Кастомна валідація { #custom-validation }
Можуть бути випадки, коли Вам потрібно провести **кастомну валідацію**, яку не можна реалізувати за допомогою параметрів, показаних вище.
Можуть бути випадки, коли вам потрібно провести **кастомну валідацію**, яку не можна реалізувати за допомогою параметрів, показаних вище.
У таких випадках ви можете використати **кастомну функцію валідації**, яка буде застосована після звичайної валідації (наприклад, після перевірки, що значення є типом `str`).
У таких випадках ви можете використати **кастомну функцію-валідатор**, яка буде застосована після звичайної валідації (наприклад, після перевірки, що значення є типом `str`).
Це можна досягти за допомогою <a href="https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator" class="external-link" target="_blank">Pydantic's `AfterValidator`</a> в середині `Annotated`.
/// tip | Підказка
/// tip | Порада
Pydantic також має <a href="https://docs.pydantic.dev/latest/concepts/validators/#field-before-validator" class="external-link" target="_blank">`BeforeValidator`</a> та інші. 🤓
///
Наприклад, цей кастомний валідатор перевіряє, чи починається ID елемента з `isbn-` для номера книги <abbr title="ISBN означає Міжнародний стандартний номер книги">ISBN</abbr> або з `imdb-` для ID URL фільму на <abbr title="IMDB (Internet Movie Database) це вебсайт з інформацією про фільми">IMDB</abbr>:
Наприклад, цей кастомний валідатор перевіряє, чи починається ID елемента з `isbn-` для номера книги <abbr title="ISBN means International Standard Book Number ISBN означає Міжнародний стандартний номер книги">ISBN</abbr> або з `imdb-` для ID URL фільму на <abbr title="IMDB (Internet Movie Database) is a website with information about movies IMDB (Internet Movie Database) це вебсайт з інформацією про фільми">IMDB</abbr>:
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *}
@@ -429,49 +412,49 @@ Pydantic також має <a href="https://docs.pydantic.dev/latest/concepts/va
///
/// tip | Підказка
/// tip | Порада
Якщо Вам потрібно виконати будь-яку валідацію, яка вимагає взаємодії з будь-яким **зовнішнім компонентом**, таким як база даних чи інший API, ви повинні замість цього використовувати **FastAPI Dependencies**. Ви дізнаєтесь про них пізніше.
Якщо вам потрібно виконати будь-яку валідацію, яка вимагає взаємодії з будь-яким **зовнішнім компонентом**, таким як база даних чи інший API, замість цього слід використовувати **FastAPI Dependencies** — ви дізнаєтесь про них пізніше.
Ці кастомні валідатори використовуються для речей, які можна перевірити лише з **тими даними**, що надані в запиті.
Ці кастомні валідатори використовуються для речей, які можна перевірити лише з **тіими самими даними**, що надані в запиті.
///
### Зрозумійте цей код
### Зрозумійте цей код { #understand-that-code }
Головний момент це використання **`AfterValidator` з функцією всередині `Annotated`**. Можете пропустити цю частину, якщо хочете. 🤸
Головний момент це використання **`AfterValidator` з функцією всередині `Annotated`**. Можете пропустити цю частину, якщо хочете. 🤸
---
Але якщо Вам цікаво розібратися в цьому конкретному прикладі коду і Вам ще не набридло, ось кілька додаткових деталей.
Але якщо вам цікаво розібратися в цьому конкретному прикладі коду і вам ще не набридло, ось кілька додаткових деталей.
#### Рядок із `value.startswith()`
#### Рядок із `value.startswith()` { #string-with-value-startswith }
Звернули увагу? Рядок із `value.startswith()` може приймати кортеж, і тоді він перевірятиме кожне значення в кортежі:
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *}
#### Випадковий елемент
#### Випадковий елемент { #a-random-item }
За допомогою `data.items()` ми отримуємо <abbr title="Об'єкт, який можна перебирати в циклі, як-от список чи множину.">ітерабельний об'єкт</abbr> із кортежами, що містять ключ і значення для кожного елемента словника.
За допомогою `data.items()` ми отримуємо <abbr title="Something we can iterate on with a for loop, like a list, set, etc. Об'єкт, який можна перебирати в циклі, як-от список чи множину.">iterable object</abbr> із кортежами, що містять ключ і значення для кожного елемента словника.
Ми перетворюємо цей ітерабельний об'єкт у звичайний `list` за допомогою `list(data.items())`.
Ми перетворюємо цей iterable object у звичайний `list` за допомогою `list(data.items())`.
Потім, використовуючи `random.choice()`, ми можемо отримати випадкове значення зі списку, тобто отримуємо кортеж із `(id, name)`. Це може бути щось на зразок `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`.
Потім, використовуючи `random.choice()`, ми можемо отримати **випадкове значення** зі списку, тобто отримуємо кортеж із `(id, name)`. Це може бути щось на зразок `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`.
Далі ми **присвоюємо ці два значення** кортежу змінним `id` і `name`.
Тож, якщо користувач не вказав ID елемента, він все одно отримає випадкову рекомендацію.
...і все це реалізовано в **одному рядку коду**. 🤯 Хіба не прекрасний Python? 🐍
...ми робимо все це в **одному простому рядку**. 🤯 Хіба ви не любите Python? 🐍
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *}
## Підсумок
## Підсумок { #recap }
Ви можете оголошувати додаткові валідації та метаінформацію для своїх параметрів.
Ви можете оголошувати додаткові валідації та метадані для ваших параметрів.
Загальні валідації та метаінформація:
Загальні валідації та метадані:
* `alias`
* `title`
@@ -486,6 +469,6 @@ Pydantic також має <a href="https://docs.pydantic.dev/latest/concepts/va
Кастомні валідації за допомогою `AfterValidator`.
У цих прикладах Ви побачили, як оголошувати валідації для значень `str`.
У цих прикладах ви побачили, як оголошувати валідації для значень `str`.
Дивіться наступні розділи, щоб дізнатися, як оголошувати валідації для інших типів, наприклад чисел.

View File

@@ -1,10 +1,10 @@
# Query Параметри
# Query параметри { #query-parameters }
Коли Ви оголошуєте інші параметри функції, які не є частиною параметрів шляху, вони автоматично інтерпретуються як "query" параметри.
Коли ви оголошуєте інші параметри функції, які не є частиною параметрів шляху, вони автоматично інтерпретуються як параметри «query».
{* ../../docs_src/query_params/tutorial001.py hl[9] *}
{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *}
Query параметри — це набір пар ключ-значення, що йдуть після символу `?` в URL, розділені символами `&`.
Query — це набір пар ключ-значення, що йдуть після символу `?` в URL, розділені символами `&`.
Наприклад, в URL:
@@ -12,41 +12,41 @@ Query параметри — це набір пар ключ-значення,
http://127.0.0.1:8000/items/?skip=0&limit=10
```
...query параметрами є:
...параметрами query є:
* `skip`: зі значенням `0`
* `limit`: зі значенням `10`
Оскільки вони є частиною URL, вони "за замовчуванням" є рядками.
Оскільки вони є частиною URL, вони «природно» є рядками.
Але коли Ви оголошуєте їх із типами Python (у наведеному прикладі як `int`), вони перетворюються на цей тип і проходять перевірку відповідності.
Але коли ви оголошуєте їх із типами Python (у наведеному прикладі як `int`), вони перетворюються на цей тип і проходять перевірку відповідності.
Увесь той самий процес, який застосовується до параметрів шляху, також застосовується до query параметрів:
Увесь той самий процес, який застосовується до параметрів шляху, також застосовується до параметрів query:
* Підтримка в редакторі (автодоповнення, перевірка помилок)
* <abbr title="перетворення рядка, що надходить з HTTP-запиту, у типи даних Python">"Парсинг"</abbr> даних
* Підтримка в редакторі (очевидно)
* <abbr title="converting the string that comes from an HTTP request into Python data перетворення рядка, що надходить з HTTP-запиту, у дані Python">«parsing»</abbr> даних
* Валідація даних
* Автоматична документація
## Значення за замовчуванням { #defaults }
## Значення за замовчуванням
Оскільки query параметри не є фіксованою частиною шляху, вони можуть бути необов’язковими та мати значення за замовчуванням.
Оскільки параметри query не є фіксованою частиною шляху, вони можуть бути необов’язковими та мати значення за замовчуванням.
У наведеному вище прикладі вони мають значення за замовчуванням: `skip=0` і `limit=10`.
Отже, результат переходу за URL:
Отже, перехід за URL:
```
http://127.0.0.1:8000/items/
```
буде таким самим, як і перехід за посиланням:
```
http://127.0.0.1:8000/items/?skip=0&limit=10
```
Але якщо Ви перейдете, наприклад, за посиланням:
Але якщо ви перейдете, наприклад, за посиланням:
```
http://127.0.0.1:8000/items/?skip=20
@@ -54,12 +54,12 @@ http://127.0.0.1:8000/items/?skip=20
Значення параметрів у вашій функції будуть такими:
* `skip=20`: оскільки Ви вказали його в URL
* `skip=20`: оскільки ви вказали його в URL
* `limit=10`: оскільки це значення за замовчуванням
## Необов'язкові параметри
## Необов'язкові параметри { #optional-parameters }
Аналогічно, Ви можете оголосити необов’язкові query параметри, встановивши для них значення за замовчуванням `None`:
Так само ви можете оголосити необов’язкові параметри query, встановивши для них значення за замовчуванням `None`:
{* ../../docs_src/query_params/tutorial002_py310.py hl[7] *}
@@ -67,18 +67,17 @@ http://127.0.0.1:8000/items/?skip=20
/// check | Примітка
Також зверніть увагу, що **FastAPI** достатньо розумний, щоб визначити, що параметр шляху `item_id` є параметром шляху, а `q` — ні, отже, це query параметр.
Також зверніть увагу, що **FastAPI** достатньо розумний, щоб визначити, що параметр шляху `item_id` є параметром шляху, а `q` — ні, отже, це параметр query.
///
## Перетворення типу Query параметра
## Перетворення типу параметра query { #query-parameter-type-conversion }
Ви також можете оголошувати параметри типу `bool`, і вони будуть автоматично конвертовані:
{* ../../docs_src/query_params/tutorial003_py310.py hl[7] *}
У цьому випадку, якщо Ви звернетесь до:
У цьому випадку, якщо ви перейдете за:
```
http://127.0.0.1:8000/items/foo?short=1
@@ -108,38 +107,38 @@ http://127.0.0.1:8000/items/foo?short=on
http://127.0.0.1:8000/items/foo?short=yes
```
або будь-який інший варіант написання (великі літери, перша літера велика тощо), ваша функція побачить параметр `short` зі значенням `True` з типом даних `bool`. В іншому випадку `False`.
## Кілька path і query параметрів
Ви можете одночасно оголошувати кілька path і query параметрів, і **FastAPI** автоматично визначить, який з них до чого належить.
або будь-який інший варіант написання (великі літери, перша літера велика тощо), ваша функція побачить параметр `short` зі значенням `True` типу `bool`. В іншому випадку `False`.
Не потрібно дотримуватись певного порядку їх оголошення.
## Кілька path і query параметрів { #multiple-path-and-query-parameters }
Ви можете одночасно оголошувати кілька параметрів шляху та параметрів query, **FastAPI** знає, який з них який.
І вам не потрібно оголошувати їх у якомусь конкретному порядку.
Вони визначаються за назвою:
{* ../../docs_src/query_params/tutorial004_py310.py hl[6,8] *}
## Обов’язкові Query параметри
## Обов’язкові параметри query { #required-query-parameters }
Якщо Ви оголошуєте значення за замовчуванням для параметрів, які не є path-параметрами (у цьому розділі ми бачили поки що лише path параметри), тоді вони стають необов’язковими.
Коли ви оголошуєте значення за замовчуванням для не-path-параметрів (поки що ми бачили лише параметри query), тоді вони не є обов’язковими.
Якщо Ви не хочете вказувати конкретні значення, але хочете зробити параметр опціональним, задайте `None` як значення за замовчуванням.
Якщо ви не хочете задавати конкретне значення, а просто зробити параметр необов’язковим, задайте `None` як значення за замовчуванням.
Але якщо Ви хочете зробити query параметр обов’язковим, просто не вказуйте для нього значення за замовчуванням:
Але якщо ви хочете зробити параметр query обов’язковим, просто не вказуйте для нього значення за замовчуванням:
{* ../../docs_src/query_params/tutorial005.py hl[6:7] *}
{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *}
Тут `needy` обов’язковий query параметр типу `str`.
Тут параметр query `needy` обов’язковий параметр query типу `str`.
Якщо Ви відкриєте у браузері URL-адресу:
Якщо ви відкриєте у браузері URL-адресу:
```
http://127.0.0.1:8000/items/foo-item
```
...без додавання обов’язкового параметра `needy`, Ви побачите помилку:
...без додавання обов’язкового параметра `needy`, ви побачите помилку на кшталт:
```JSON
{
@@ -163,7 +162,7 @@ http://127.0.0.1:8000/items/foo-item
http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
```
...цей запит поверне:
...це спрацює:
```JSON
{
@@ -172,20 +171,18 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
}
```
Звичайно, Ви можете визначити деякі параметри як обов’язкові, інші зі значенням за замовчуванням, а ще деякі — повністю опціональні:
І звісно, ви можете визначити деякі параметри як обов’язкові, деякі — зі значенням за замовчуванням, а деякі — повністю необов’язкові:
{* ../../docs_src/query_params/tutorial006_py310.py hl[8] *}
У цьому випадку є 3 query параметри:
У цьому випадку є 3 параметри query:
* `needy`, обов’язковий `str`.
* `skip`, `int` зі значенням за замовчуванням `0`.
* `limit`, опціональний `int`.
* `limit`, необов’язковий `int`.
/// tip | Порада
/// tip | Підказка
Ви також можете використовувати `Enum`-и, так само як і з [Path Parameters](path-params.md#predefined-values){.internal-link target=_blank}.
Ви також можете використовувати `Enum` так само, як і з [Path Parameters](path-params.md#predefined-values){.internal-link target=_blank}.
///

View File

@@ -1,56 +1,56 @@
# Запит файлів
# Запит файлів { #request-files }
Ви можете визначити файли, які будуть завантажуватися клієнтом, використовуючи `File`.
/// info | Інформація
Щоб отримувати завантажені файли, спочатку встановіть <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">python-multipart</a>.
Щоб отримувати завантажені файли, спочатку встановіть <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a>.
Переконайтеся, що Ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його та встановили пакет, наприклад:
Переконайтеся, що ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його, а потім встановили пакет, наприклад:
```console
$ pip install python-multipart
```
Це необхідно, оскільки завантажені файли передаються у вигляді "форматованих даних форми".
Це необхідно, оскільки завантажені файли передаються у вигляді «form data».
///
## Імпорт `File`
## Імпорт `File` { #import-file }
Імпортуйте `File` та `UploadFile` з `fastapi`:
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *}
## Визначення параметрів `File`
## Визначення параметрів `File` { #define-file-parameters }
Створіть параметри файлів так само як Ви б створювали `Body` або `Form`:
Створіть параметри файлів так само як ви б створювали `Body` або `Form`:
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *}
/// info | Інформація
`File` — це клас, який безпосередньо успадковує `Form`.
`File` — це клас, який безпосередньо успадковує `Form`.
Але пам’ятайте, що коли Ви імпортуєте `Query`, `Path`, `File` та інші з `fastapi`, це насправді функції, які повертають спеціальні класи.
Але пам’ятайте, що коли ви імпортуєте `Query`, `Path`, `File` та інші з `fastapi`, це насправді функції, які повертають спеціальні класи.
///
/// tip | Підказка
/// tip | Порада
Щоб оголосити тіла файлів, Вам потрібно використовувати `File`, тому що інакше параметри будуть інтерпретовані як параметри запиту або параметри тіла (JSON).
Щоб оголосити тіла файлів, вам потрібно використовувати `File`, тому що інакше параметри будуть інтерпретовані як параметри запиту або параметри тіла (JSON).
///
Файли будуть завантажені у вигляді "форматованих даних форми".
Файли будуть завантажені у вигляді «form data».
Якщо Ви оголосите тип параметра функції обробника маршруту як `bytes`, **FastAPI** прочитає файл за Вас, і Ви отримаєте його вміст у вигляді `bytes`.
Якщо ви оголосите тип параметра *функції операції шляху* як `bytes`, **FastAPI** прочитає файл за вас, і ви отримаєте його вміст у вигляді `bytes`.
Однак майте на увазі, що весь вміст буде збережено в пам'яті. Це працюватиме добре для малих файлів.
Майте на увазі, що це означає, що весь вміст буде збережено в пам'яті. Це працюватиме добре для малих файлів.
Але в деяких випадках Вам може знадобитися `UploadFile`.
Але є кілька випадків, у яких вам може бути корисно використовувати `UploadFile`.
## Параметри файлу з `UploadFile`
## Параметри файлу з `UploadFile` { #file-parameters-with-uploadfile }
Визначте параметр файлу з типом `UploadFile`:
@@ -59,38 +59,39 @@ $ pip install python-multipart
Використання `UploadFile` має кілька переваг перед `bytes`:
* Вам не потрібно використовувати `File()` у значенні за замовчуванням параметра.
* Використовується "буферизований" файл:
* Файл зберігається в пам'яті до досягнення певного обмеження, після чого він записується на диск.
* Це означає, що він добре працює для великих файлів, таких як зображення, відео, великі двійкові файли тощо, не споживаючи всю пам'ять.
Ви можете отримати метадані про завантажений файл.
* Він має <a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">file-like</a> `асинхронний файловий інтерфейс` interface.
* Він надає фактичний об'єкт Python <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a>, який можна передавати безпосередньо іншим бібліотекам.
* Використовується «spooled» файл:
* Файл зберігається в пам'яті до досягнення максимального обмеження розміру, після чого він буде збережений на диску.
* Це означає, що він добре працюватиме для великих файлів, таких як зображення, відео, великі двійкові файли тощо, не споживаючи всю пам'ять.
* Ви можете отримати метадані про завантажений файл.
* Він має <a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">file-like</a> `async` інтерфейс.
* Він надає фактичний об'єкт Python <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a>, який можна передавати безпосередньо іншим бібліотекам, що очікують file-like об'єкт.
### `UploadFile`
### `UploadFile` { #uploadfile }
`UploadFile` має такі атрибути:
* `filename`: Рядок `str` з оригінальною назвою файлу, який був завантажений (наприклад, `myimage.jpg`).
* `content_type`: Рядок `str` з MIME-типом (наприклад, `image/jpeg`).
* `file`: Об'єкт <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">SpooledTemporaryFile</a> (<a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">файлоподібний</a> об'єкт). Це фактичний файловий об'єкт Python, який можна безпосередньо передавати іншим функціям або бібліотекам, що очікують "файлоподібний" об'єкт.
* `content_type`: Рядок `str` з типом вмісту (MIME type / media type) (наприклад, `image/jpeg`).
* `file`: <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a> (<a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">file-like</a> об'єкт). Це фактичний файловий об'єкт Python, який ви можете передавати безпосередньо іншим функціям або бібліотекам, що очікують «file-like» об'єкт.
`UploadFile` має такі асинхронні `async` методи. Вони викликають відповідні методи файлу під капотом (використовуючи внутрішній `SpooledTemporaryFile`).
`UploadFile` має такі асинхронні `async` методи. Вони всі викликають відповідні методи файлу під капотом (використовуючи внутрішній `SpooledTemporaryFile`).
* `write(data)`: Записує `data` (`str` або `bytes`) у файл.
* `read(size)`: Читає `size` (`int`) байтів/символів з файлу.
* `seek(offset)`: Переміщується до позиції `offset` (`int`) у файлі.
* Наприклад, `await myfile.seek(0)` поверне курсор на початок файлу.
* This is especially useful if you run `await myfile.read()` once and then need to read the contents again. Це особливо корисно, якщо Ви виконуєте await `await myfile.read()` один раз, а потім потрібно знову прочитати вміст.
* `seek(offset)`: Переходить до байтової позиції `offset` (`int`) у файлі.
* Наприклад, `await myfile.seek(0)` перейде на початок файлу.
* Це особливо корисно, якщо ви виконаєте `await myfile.read()` один раз, а потім потрібно знову прочитати вміст.
* `close()`: Закриває файл.
Оскільки всі ці методи є асинхронними `async`, Вам потрібно використовувати "await":
Оскільки всі ці методи є асинхронними `async` методами, вам потрібно їх «await»-ити.
Наприклад, всередині `async` *функції обробки шляху* Ви можете отримати вміст за допомогою:
Наприклад, всередині `async` *функції операції шляху* ви можете отримати вміст за допомогою:
```Python
contents = await myfile.read()
```
Якщо Ви знаходитесь у звичайній `def` *функції обробки шляху*, Ви можете отримати доступ до `UploadFile.file` безпосередньо, наприклад:
Якщо ви знаходитесь у звичайній `def` *функції операції шляху*, ви можете отримати доступ до `UploadFile.file` безпосередньо, наприклад:
```Python
contents = myfile.file.read()
@@ -98,57 +99,57 @@ contents = myfile.file.read()
/// note | Технічні деталі `async`
Коли Ви використовуєте `async` методи, **FastAPI** виконує файлові операції у пулі потоків та очікує їх завершення.
Коли ви використовуєте `async` методи, **FastAPI** виконує файлові методи у пулі потоків і очікує на них.
///
/// note | Технічні деталі Starlette
`UploadFile` у **FastAPI** успадковується безпосередньо від `UploadFile` у **Starlette**, але додає деякі необхідні частини, щоб зробити його сумісним із **Pydantic** та іншими компонентами FastAPI.
`UploadFile` у **FastAPI** успадковується безпосередньо від `UploadFile` у **Starlette**, але додає деякі необхідні частини, щоб зробити його сумісним із **Pydantic** та іншими частинами FastAPI.
///
## Що таке "Form Data"
## Що таке «Form Data» { #what-is-form-data }
Спосіб, у який HTML-форми (`<form></form>`) надсилають дані на сервер, зазвичай використовує "спеціальне" кодування, відмінне від JSON.
Спосіб, у який HTML-форми (`<form></form>`) надсилають дані на сервер, зазвичай використовує «спеціальне» кодування для цих даних, відмінне від JSON.
**FastAPI** забезпечує правильне зчитування цих даних з відповідної частини запиту, а не з JSON.
**FastAPI** забезпечить зчитування цих даних з правильного місця, а не з JSON.
/// note | Технічні деталі
Дані з форм зазвичай кодуються за допомогою "media type" `application/x-www-form-urlencoded`, якщо вони не містять файлів.
Дані з форм зазвичай кодуються за допомогою «media type» `application/x-www-form-urlencoded`, якщо вони не містять файлів.
Але якщо форма містить файли, вона кодується у форматі `multipart/form-data`. Якщо Ви використовуєте `File`, **FastAPI** визначить, що потрібно отримати файли з відповідної частини тіла запиту.
Але якщо форма містить файли, вона кодується як `multipart/form-data`. Якщо ви використовуєте `File`, **FastAPI** знатиме, що потрібно отримати файли з правильної частини тіла.
Щоб дізнатися більше про ці типи кодування та формові поля, ознайомтеся з <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">документацією MDN</abbr> щодо <code>POST</code></a>.
Якщо ви хочете дізнатися більше про ці типи кодування та формові поля, ознайомтеся з <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> web docs для <code>POST</code></a>.
///
/// warning | Увага
/// warning | Попередження
Ви можете оголосити кілька параметрів `File` і `Form` в *операції шляху*, але Ви не можете одночасно оголошувати поля `Body`, які мають надходити у форматі JSON, оскільки тіло запиту буде закодоване у форматі `multipart/form-data`, а не `application/json`.
Ви можете оголосити кілька параметрів `File` і `Form` в *операції шляху*, але ви не можете одночасно оголошувати поля `Body`, які ви очікуєте отримати як JSON, оскільки запит матиме тіло, закодоване як `multipart/form-data`, а не `application/json`.
Це не обмеження **FastAPI**, а особливість протоколу HTTP.
Це не обмеження **FastAPI**, а частина протоколу HTTP.
///
## Опціональне Завантаження Файлів
## Необов’язкове завантаження файлу { #optional-file-upload }
Файл можна зробити необов’язковим, використовуючи стандартні анотації типів і встановлюючи значення за замовчуванням `None`:
Ви можете зробити файл необов’язковим, використовуючи стандартні анотації типів і встановивши значення за замовчуванням `None`:
{* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *}
## `UploadFile` із Додатковими Мета Даними
## `UploadFile` із додатковими метаданими { #uploadfile-with-additional-metadata }
Ви також можете використовувати `File()` разом із `UploadFile`, наприклад, для встановлення додаткових метаданих:
Ви також можете використовувати `File()` разом із `UploadFile`, наприклад, щоб встановити додаткові метадані:
{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *}
## Завантаження Кількох Файлів
## Завантаження кількох файлів { #multiple-file-uploads }
Можна завантажувати кілька файлів одночасно.
Вони будуть пов’язані з одним і тим самим "form field", який передається у вигляді "form data".
Вони будуть пов’язані з одним і тим самим «form field», який передається у вигляді «form data».
Щоб це реалізувати, потрібно оголосити список `bytes` або `UploadFile`:
@@ -160,16 +161,16 @@ contents = myfile.file.read()
Ви також можете використати `from starlette.responses import HTMLResponse`.
**FastAPI** надає ті ж самі `starlette.responses`, що й `fastapi.responses`, для зручності розробників. Однак більшість доступних відповідей надходять безпосередньо від Starlette.
**FastAPI** надає ті ж самі `starlette.responses`, що й `fastapi.responses`, просто для зручності для вас, розробника. Але більшість доступних відповідей надходять безпосередньо від Starlette.
///
### Завантаження декількох файлів із додатковими метаданими
### Завантаження кількох файлів із додатковими метаданими { #multiple-file-uploads-with-additional-metadata }
Так само як і раніше, Ви можете використовувати `File()`, щоб встановити додаткові параметри навіть для `UploadFile`:
Так само як і раніше, ви можете використовувати `File()`, щоб встановити додаткові параметри навіть для `UploadFile`:
{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *}
## Підсумок
## Підсумок { #recap }
Використовуйте `File`, `bytes`та `UploadFile`, щоб оголошувати файли для завантаження у запитах, які надсилаються у вигляді form data.
Використовуйте `File`, `bytes` та `UploadFile`, щоб оголошувати файли для завантаження в запиті, надіслані у вигляді form data.

View File

@@ -1,12 +1,12 @@
# Моделі форм (Form Models)
# Моделі форм { #form-models }
У FastAPI Ви можете використовувати **Pydantic-моделі** для оголошення **полів форми**.
У FastAPI ви можете використовувати **Pydantic-моделі** для оголошення **полів форми**.
/// info | Інформація
Щоб використовувати форми, спочатку встановіть <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">python-multipart</a>.
Щоб використовувати форми, спочатку встановіть <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a>.
Переконайтеся, що Ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його, а потім встановили бібліотеку, наприклад:
Переконайтеся, що ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його, а потім встановили його, наприклад:
```console
$ pip install python-multipart
@@ -14,21 +14,21 @@ $ pip install python-multipart
///
/// note | Підказка
/// note | Примітка
Ця функція підтримується, починаючи з FastAPI версії `0.113.0`. 🤓
Це підтримується, починаючи з FastAPI версії `0.113.0`. 🤓
///
## Використання Pydantic-моделей для форм
## Pydantic-моделі для форм { #pydantic-models-for-forms }
Вам просто потрібно оголосити **Pydantic-модель** з полями, які Ви хочете отримати як **поля форми**, а потім оголосити параметр як `Form`:
Вам просто потрібно оголосити **Pydantic-модель** з полями, які ви хочете отримати як **поля форми**, а потім оголосити параметр як `Form`:
{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *}
**FastAPI** **витягне** дані для **кожного поля** з **формових даних** у запиті та надасть вам Pydantic-модель, яку Ви визначили.
**FastAPI** **витягне** дані для **кожного поля** з **формових даних** у запиті та надасть вам Pydantic-модель, яку ви визначили.
## Перевірка документації
## Перевірте документацію { #check-the-docs }
Ви можете перевірити це в UI документації за `/docs`:
@@ -36,13 +36,13 @@ $ pip install python-multipart
<img src="/img/tutorial/request-form-models/image01.png">
</div>
## Заборона додаткових полів форми
## Забороніть додаткові поля форми { #forbid-extra-form-fields }
У деяких особливих випадках (ймовірно, рідко) Ви можете **обмежити** форму лише тими полями, які були оголошені в Pydantic-моделі, і **заборонити** будь-які **додаткові** поля.
У деяких особливих випадках (ймовірно, не дуже поширених) ви можете **обмежити** поля форми лише тими, які були оголошені в Pydantic-моделі. І **заборонити** будь-які **додаткові** поля.
/// note | Підказка
/// note | Примітка
Ця функція підтримується, починаючи з FastAPI версії `0.114.0`. 🤓
Це підтримується, починаючи з FastAPI версії `0.114.0`. 🤓
///
@@ -52,7 +52,7 @@ $ pip install python-multipart
Якщо клієнт спробує надіслати додаткові дані, він отримає **відповідь з помилкою**.
Наприклад, якщо клієнт спробує надіслати наступні поля форми:
Наприклад, якщо клієнт спробує надіслати поля форми:
* `username`: `Rick`
* `password`: `Portal Gun`
@@ -73,6 +73,6 @@ $ pip install python-multipart
}
```
## Підсумок
## Підсумок { #summary }
Ви можете використовувати Pydantic-моделі для оголошення полів форми у FastAPI. 😎
У FastAPI ви можете використовувати Pydantic-моделі для оголошення полів форми. 😎

View File

@@ -1,10 +1,10 @@
# Запити з формами та файлами
# Запити з формами та файлами { #request-forms-and-files }
У FastAPI Ви можете одночасно отримувати файли та поля форми, використовуючи `File` і `Form`.
Ви можете одночасно визначати файли та поля форми, використовуючи `File` і `Form`.
/// info | Інформація
Щоб отримувати завантажені файли та/або дані форми, спочатку встановіть <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">python-multipart</a>.
Щоб отримувати завантажені файли та/або дані форми, спочатку встановіть <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a>.
Переконайтеся, що Ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його, а потім встановили бібліотеку, наприклад:
@@ -14,21 +14,21 @@ $ pip install python-multipart
///
## Імпорт `File` та `Form`
## Імпорт `File` та `Form` { #import-file-and-form }
{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *}
## Оголошення параметрів `File` та `Form`
## Оголошення параметрів `File` та `Form` { #define-file-and-form-parameters }
Створіть параметри файлів та форми так само як і для `Body` або `Query`:
{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *}
Файли та поля форми будуть завантажені як формові дані, і Ви отримаєте як файли, так і введені користувачем поля.
Файли та поля форми будуть завантажені як формові дані, і Ви отримаєте файли та поля форми.
Ви також можете оголосити деякі файли як `bytes`, а деякі як `UploadFile`.
/// warning | Увага
/// warning | Попередження
Ви можете оголосити кілька параметрів `File` і `Form` в операції *шляху*, але не можете одночасно оголошувати `Body`-поля, які очікуєте отримати у форматі JSON, оскільки запит матиме тіло, закодоване за допомогою `multipart/form-data`, а не `application/json`.
@@ -36,6 +36,6 @@ $ pip install python-multipart
///
## Підсумок
## Підсумок { #recap }
Використовуйте `File` та `Form` разом, коли вам потрібно отримувати дані форми та файли в одному запиті.
Використовуйте `File` та `Form` разом, коли вам потрібно отримувати дані та файли в одному запиті.

View File

@@ -1,12 +1,12 @@
# Дані форми
# Дані форми { #form-data }
Якщо Вам потрібно отримувати поля форми замість JSON, Ви можете використовувати `Form`.
Якщо вам потрібно отримувати поля форми замість JSON, ви можете використовувати `Form`.
/// info | Інформація
Щоб використовувати форми, спочатку встановіть <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a>.
Переконайтеся, що Ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його, і потім встановили бібліотеку, наприклад:
Переконайтеся, що ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його, і потім встановили бібліотеку, наприклад:
```console
$ pip install python-multipart
@@ -14,23 +14,23 @@ $ pip install python-multipart
///
## Імпорт `Form`
## Імпорт `Form` { #import-form }
Імпортуйте `Form` з `fastapi`:
{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *}
## Оголошення параметрів `Form`
## Оголошення параметрів `Form` { #define-form-parameters }
Створюйте параметри форми так само як Ви б створювали `Body` або `Query`:
Створюйте параметри форми так само як ви б створювали `Body` або `Query`:
{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *}
Наприклад, один зі способів використання специфікації OAuth2 (так званий "password flow") вимагає надсилати `username` та `password` як поля форми.
<abbr title="Специфікація">spec</abbr> вимагає, щоб ці поля мали точні назви `username` і `password` та надсилалися у вигляді полів форми, а не JSON.
<abbr title="specification">spec</abbr> вимагає, щоб ці поля мали точні назви `username` і `password` та надсилалися у вигляді полів форми, а не JSON.
З `Form` Ви можете оголошувати ті ж конфігурації, що і з `Body` (та `Query`, `Path`, `Cookie`), включаючи валідацію, приклади, псевдоніми (наприклад, `user-name` замість `username`) тощо.
З `Form` ви можете оголошувати ті ж конфігурації, що і з `Body` (та `Query`, `Path`, `Cookie`), включаючи валідацію, приклади, псевдоніми (наприклад, `user-name` замість `username`) тощо.
/// info | Інформація
@@ -44,7 +44,7 @@ $ pip install python-multipart
///
## Про "поля форми"
## Про "поля форми" { #about-form-fields }
HTML-форми (`<form></form>`) надсилають дані на сервер у "спеціальному" кодуванні, яке відрізняється від JSON.
@@ -56,18 +56,18 @@ HTML-форми (`<form></form>`) надсилають дані на серве
Але якщо форма містить файли, вона кодується як `multipart/form-data`. Ви дізнаєтеся про обробку файлів у наступному розділі.
Якщо Ви хочете дізнатися більше про ці кодування та поля форм, зверніться до <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> вебдокументації для <code>POST</code></a>.
Якщо ви хочете дізнатися більше про ці кодування та поля форм, зверніться до <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> вебдокументації для <code>POST</code></a>.
///
/// warning | Попередження
Ви можете оголосити кілька параметрів `Form` в *операції шляху*, але не можете одночасно оголосити поля `Body`, які Ви очікуєте отримати у форматі JSON, оскільки тіло запиту буде закодовано у форматі `application/x-www-form-urlencoded`, а не `application/json`.
Ви можете оголосити кілька параметрів `Form` в *операції шляху*, але не можете одночасно оголосити поля `Body`, які ви очікуєте отримати у форматі JSON, оскільки запит матиме тіло, закодоване як `application/x-www-form-urlencoded`, а не `application/json`.
Це не обмеження **FastAPI**, а частина HTTP-протоколу.
///
## Підсумок
## Підсумок { #recap }
Використовуйте `Form` для оголошення вхідних параметрів у вигляді даних форми.

View File

@@ -1,36 +1,35 @@
# Модель відповіді — Тип, що повертається
# Модель відповіді — Тип, що повертається { #response-model-return-type }
Ви можете оголосити тип, який використовуватиметься у відповіді, за допомогою *анотації типу, що повертається* *функцією операцією шляху* (path operation)
Ви можете оголосити тип, який використовуватиметься у відповіді, анотувавши **тип повернення** *функції операції шляху*.
**Анотацію типу** можна вказати так само як і для вхідних **параметрів** функції: це можуть бути моделі Pydantic, списки (lists), словники (dictionaries), скалярні значення, як-от цілі числа (integers), булеві значення (booleans) тощо.
**Анотації типів** можна використовувати так само, як і для вхідних даних у **параметрах** функції: можна використовувати моделі Pydantic, списки, словники, скалярні значення, як-от цілі числа, булеві значення тощо.
{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *}
FastAPI використовуватиме цей тип, щоб:
FastAPI використовуватиме цей тип повернення, щоб:
* **Перевірити правильність** повернених даних.
* Якщо дані не валідні (наприклад, відсутнє поле), це означає, що Ваш код додатку працює некоректно і не повертає те, що повинен. У такому випадку FastAPI поверне помилку сервера, замість того щоб віддати недопустимі дані. Так Ви та Ваші клієнти будете впевнені, що отримуєте очікувані дані у правильному форматі.
* Додати **JSON Schema** відповіді до специфікації OpenAPI в *операціях шляху*.
* Якщо дані не валідні (наприклад, відсутнє поле), це означає, що *ваш* код застосунку зламаний, не повертає те, що повинен, і буде повернуто помилку сервера замість некоректних даних. Так ви та ваші клієнти можете бути впевнені, що отримаєте дані й очікувану структуру даних.
* Додати **JSON Schema** для відповіді в OpenAPI *операції шляху*.
* Це буде використано в **автоматичній документації**.
* А також інструментами, які автоматично генерують клієнтський код.
* Це також буде використано інструментами, які автоматично генерують клієнтський код.
Але найголовніше:
* FastAPI **обмежить та відфільтрує** вихідні дані відповідно до типу, вказаного у відповіді.
* Це особливо важливо для **безпеки**. Деталі нижче.
* Це **обмежить та відфільтрує** вихідні дані до того, що визначено в типі повернення.
* Це особливо важливо для **безпеки**, нижче ми побачимо про це більше.
## Параметр `response_model`
## Параметр `response_model` { #response-model-parameter }
Іноді Вам потрібно або зручно повертати інші типи даних, ніж ті, що зазначені як тип відповіді.
Є випадки, коли вам потрібно або ви хочете повертати дані, які не зовсім відповідають тому, що оголошено типом.
Наприклад, Ви можете **повертати словник** або об’єкт бази даних, але **оголосити модель Pydantic** як модель відповіді. Тоді модель Pydantic автоматично оброблятиме валідацію, документацію тощо.
Наприклад, ви можете захотіти **повертати словник** або об’єкт бази даних, але **оголосити його як модель Pydantic**. Таким чином модель Pydantic виконуватиме всю документацію даних, валідацію тощо для об’єкта, який ви повернули (наприклад, словника або об’єкта бази даних).
Якщо Ви додасте анотацію типу для повернення, редактор коду або mypy можуть поскаржитися, що функція повертає інший тип (наприклад, dict замість Item).
Якщо ви додали анотацію типу повернення, інструменти та редактори скаржитимуться (коректною) помилкою, повідомляючи, що ваша функція повертає тип (наприклад, dict), який відрізняється від того, що ви оголосили (наприклад, модель Pydantic).
У таких випадках можна скористатися параметром `response_model` в декораторі маршруту (наприклад, @app.get()).
У таких випадках можна скористатися параметром *декоратора операції шляху* `response_model` замість типу повернення.
Параметр `response_model` працює з будь-яким *оператором шляху*:
Ви можете використовувати параметр `response_model` у будь-якій з *операцій шляху*:
* `@app.get()`
* `@app.post()`
@@ -42,33 +41,33 @@ FastAPI використовуватиме цей тип, щоб:
/// note | Примітка
Зверніть увагу, що `response_model` є параметром методу-декоратора (`get`, `post`, тощо), а не *функцією операцією шляху* (path operation function), як це робиться з параметрами або тілом запиту.
Зверніть увагу, що `response_model` є параметром методу «декоратора» (`get`, `post` тощо). А не вашої *функції операції шляху*, як усі параметри та тіло.
///
`response_model` приймає такий самий тип, який Ви б вказали для поля моделі Pydantic. Тобто це може бути як Pydantic-модель, так і, наприклад, `list` із моделей Pydantic `List[Item]`.
`response_model` приймає такий самий тип, який ви б вказали для поля моделі Pydantic, тобто це може бути модель Pydantic, але також це може бути, наприклад, `list` моделей Pydantic, як-от `List[Item]`.
FastAPI використовуватиме `response_model` для створення документації, валідації даних та — найважливіше — **перетворення та фільтрації вихідних даних** згідно з оголошеним типом.
FastAPI використовуватиме цей `response_model` для виконання всієї документації даних, валідації тощо, а також для **перетворення та фільтрації вихідних даних** до оголошеного типу.
/// tip | Порада
Якщо у Вас увімкнено сувору перевірку типів у редакторі, mypy тощо, Ви можете оголосити тип повернення функції як `Any`.
Якщо у вас увімкнено сувору перевірку типів у редакторі, mypy тощо, ви можете оголосити тип повернення функції як `Any`.
Таким чином, Ви повідомляєте редактору, що свідомо повертаєте будь-що. Але FastAPI усе одно виконуватиме створення документації, валідацію, фільтрацію тощо за допомогою параметра `response_model`.
Таким чином, ви повідомляєте редактору, що свідомо повертаєте будь-що. Але FastAPI усе одно виконуватиме документацію даних, валідацію, фільтрацію тощо за допомогою `response_model`.
///
### Пріоритет `response_model`
### Пріоритет `response_model` { #response-model-priority }
Якщо Ви вказуєте і тип повернення, і `response_model`, то FastAPI використовуватиме `response_model` з пріоритетом.
Якщо ви оголошуєте і тип повернення, і `response_model`, то `response_model` матиме пріоритет і буде використаний FastAPI.
Таким чином, Ви можете додати правильні анотації типів до ваших функцій, навіть якщо вони повертають тип, відмінний від `response_model`. Це буде корисно для редакторів коду та інструментів, таких як mypy. І при цьому FastAPI продовжить виконувати валідацію даних, генерувати документацію тощо на основі `response_model`.
Таким чином ви можете додати правильні анотації типів до ваших функцій, навіть коли повертаєте тип, відмінний від моделі відповіді, щоб це використовували редактор і інструменти на кшталт mypy. І при цьому FastAPI все одно виконуватиме валідацію даних, документацію тощо, використовуючи `response_model`.
Ви також можете використати `response_model=None`, щоб вимкнути створення моделі відповіді для цієї *операції шляху*. Це може знадобитися, якщо Ви додаєте анотації типів до об'єктів, які не є допустимими полями Pydantic приклад цього Ви побачите в одному з наступних розділів.
Ви також можете використати `response_model=None`, щоб вимкнути створення моделі відповіді для цієї *операції шляху*; це може знадобитися, якщо ви додаєте анотації типів для речей, які не є валідними полями Pydantic, приклад цього ви побачите в одному з розділів нижче.
## Повернути ті самі вхідні дані
## Повернути ті самі вхідні дані { #return-the-same-input-data }
Тут ми оголошуємо модель `UserIn`, яка містить звичайний текстовий пароль:
Тут ми оголошуємо модель `UserIn`, вона міститиме пароль у відкритому вигляді:
{* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *}
@@ -76,7 +75,7 @@ FastAPI використовуватиме `response_model` для створе
Щоб використовувати `EmailStr`, спочатку встановіть <a href="https://github.com/JoshData/python-email-validator" class="external-link" target="_blank">`email-validator`</a>.
Переконайтесь, що Ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його, а потім встановили пакет, наприклад:
Переконайтеся, що ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його, а потім встановили пакет, наприклад:
```console
$ pip install email-validator
@@ -90,29 +89,29 @@ $ pip install "pydantic[email]"
///
І ми використовуємо цю модель, щоб оголосити і вхідні, і вихідні дані:
І ми використовуємо цю модель, щоб оголосити наші вхідні дані, і цю ж модель, щоб оголосити наші вихідні дані:
{* ../../docs_src/response_model/tutorial002_py310.py hl[16] *}
Тепер, коли браузер створює користувача з паролем, API поверне той самий пароль у відповіді.
Тепер, щоразу коли браузер створює користувача з паролем, API поверне той самий пароль у відповіді.
У цьому випадку це може не бути проблемою, адже саме користувач надіслав пароль.
У цьому випадку це може не бути проблемою, адже це той самий користувач надсилає пароль.
Але якщо ми використаємо цю ж модель для іншої операції шляху, ми можемо випадково надіслати паролі наших користувачів кожному клієнту.
Але якщо ми використаємо цю ж модель для іншої *операції шляху*, ми можемо надсилати паролі наших користувачів кожному клієнту.
/// danger | Обережно
Ніколи не зберігайте пароль користувача у відкритому вигляді та не надсилайте його у відповіді, якщо тільки Ви не знаєте всі ризики і точно розумієте, що робите.
Ніколи не зберігайте пароль користувача у відкритому вигляді та не надсилайте його у відповіді таким чином, якщо тільки ви не знаєте всіх застережень і точно розумієте, що робите.
///
## Додайте окрему вихідну модель
## Додати вихідну модель { #add-an-output-model }
Замість цього ми можемо створити вхідну модель з відкритим паролем і вихідну модель без нього:
Замість цього ми можемо створити вхідну модель з паролем у відкритому вигляді і вихідну модель без нього:
{* ../../docs_src/response_model/tutorial003_py310.py hl[9,11,16] *}
Тут, навіть якщо *функція операції шляху* повертає об'єкт користувача, який містить пароль:
Тут, хоча наша *функція операції шляху* повертає того самого вхідного користувача, який містить пароль:
{* ../../docs_src/response_model/tutorial003_py310.py hl[24] *}
@@ -120,107 +119,107 @@ $ pip install "pydantic[email]"
{* ../../docs_src/response_model/tutorial003_py310.py hl[22] *}
Таким чином, **FastAPI** автоматично відфільтрує всі дані, які не вказані у вихідній моделі (за допомогою Pydantic).
Таким чином, **FastAPI** подбає про фільтрацію всіх даних, які не оголошені у вихідній моделі (використовуючи Pydantic).
### `response_model` або тип повернення
### `response_model` або тип повернення { #response-model-or-return-type }
У цьому випадку, оскільки дві моделі різні, якщо ми анотуємо тип повернення функції як `UserOut`, редактор і такі інструменти, як mypy, видадуть помилку, бо фактично ми повертаємо інший тип.
У цьому випадку, оскільки дві моделі різні, якщо ми анотуємо тип повернення функції як `UserOut`, редактор і інструменти скаржитимуться, що ми повертаємо невалідний тип, адже це різні класи.
Тому в цьому прикладі ми використовуємо параметр `response_model`, а не анотацію типу повернення.
Саме тому в цьому прикладі нам треба оголосити це через параметр `response_model`.
...але читайте далі, щоб дізнатися, як обійти це обмеження.
...але читайте далі нижче, щоб побачити, як це обійти.
## Тип повернення і фільтрація даних
## Тип повернення і фільтрація даних { #return-type-and-data-filtering }
Продовжимо з попереднього прикладу. Ми хотіли **анотувати функцію одним типом**, але при цьому повертати з неї більше даних.
Продовжимо з попереднього прикладу. Ми хотіли **анотувати функцію одним типом**, але хотіли мати змогу повертати з функції те, що насправді містить **більше даних**.
Ми хочемо, щоб FastAPI продовжував **фільтрувати** ці дані за допомогою response_model. Тобто навіть якщо функція повертає більше інформації, у відповіді будуть лише ті поля, які вказані у response_model.
Ми хочемо, щоб FastAPI продовжував **фільтрувати** дані, використовуючи модель відповіді. Тобто навіть якщо функція повертає більше даних, відповідь міститиме лише поля, оголошені в моделі відповіді.
У попередньому прикладі, оскільки класи були різні, нам довелося використовувати параметр `response_model`. Але це означає, що ми не отримуємо підтримки з боку редактора коду та інструментів перевірки типів щодо типу, який повертає функція.
У попередньому прикладі, оскільки класи були різні, нам довелося використовувати параметр `response_model`. Але це також означає, що ми не отримуємо підтримки від редактора та інструментів, які перевіряють тип повернення функції.
Проте в більшості випадків, коли нам потрібно зробити щось подібне, ми просто хочемо, щоб модель **відфільтрувала або прибрала** частину даних, як у цьому прикладі.
Проте в більшості випадків, коли нам потрібно зробити щось подібне, ми просто хочемо, щоб модель **відфільтрувала/прибрала** частину даних, як у цьому прикладі.
У таких випадках ми можемо використати класи та спадкування, щоб скористатися **анотаціями типів** функцій — це дає кращу підтримку з боку редактора та інструментів типу mypy, і при цьому FastAPI продовжує виконувати **фільтрацію даних** у відповіді.
І в таких випадках ми можемо використати класи та спадкування, щоб скористатися **анотаціями типів** функцій і отримати кращу підтримку в редакторі та інструментах, і при цьому зберегти **фільтрацію даних** у FastAPI.
{* ../../docs_src/response_model/tutorial003_01_py310.py hl[7:10,13:14,18] *}
Завдяки цьому ми отримуємо підтримку інструментів — від редакторів і mypy, оскільки цей код є коректним з точки зору типів, — але ми також отримуємо фільтрацію даних від FastAPI.
Завдяки цьому ми отримуємо підтримку інструментів — від редакторів і mypy, адже цей код коректний з точки зору типів, — але ми також отримуємо фільтрацію даних від FastAPI.
Як це працює? Давайте розберемося. 🤓
### Типи та підтримка інструментів
### Анотації типів і підтримка інструментів { #type-annotations-and-tooling }
Спершу подивимось, як це бачать редактори, mypy та інші інструменти.
Спершу подивімося, як це бачать редактори, mypy та інші інструменти.
`BaseUser` має базові поля. Потім `UserIn` успадковує `BaseUser` і додає поле `password`, отже, він матиме всі поля з обох моделей.
`BaseUser` має базові поля. Потім `UserIn` успадковує `BaseUser` і додає поле `password`, отже він включатиме всі поля з обох моделей.
Ми зазначаємо тип повернення функції як `BaseUser`, але фактично повертаємо екземпляр `UserIn`.
Ми анотуємо тип повернення функції як `BaseUser`, але фактично повертаємо екземпляр `UserIn`.
Редактор, mypy та інші інструменти не скаржитимуться на це, тому що з точки зору типізації `UserIn` є підкласом `BaseUser`, а це означає, що він є `валідним` типом, коли очікується будь-що, що є `BaseUser`.
Редактор, mypy та інші інструменти не скаржитимуться на це, тому що з точки зору типізації `UserIn` є підкласом `BaseUser`, а це означає, що він є *валідним* типом, коли очікується будь-що, що є `BaseUser`.
### Фільтрація даних у FastAPI
### Фільтрація даних у FastAPI { #fastapi-data-filtering }
Тепер для FastAPI він бачить тип повернення і переконується, що те, що Ви повертаєте, містить **тільки** поля, які оголошені у цьому типі.
Тепер для FastAPI він побачить тип повернення і переконається, що те, що ви повертаєте, містить **лише** поля, які оголошені у цьому типі.
FastAPI виконує кілька внутрішніх операцій з Pydantic, щоб гарантувати, що правила наслідування класів не застосовуються для фільтрації повернених даних, інакше Ви могли б повернути значно більше даних, ніж очікували.
FastAPI виконує кілька внутрішніх операцій з Pydantic, щоб гарантувати, що ті самі правила наслідування класів не застосовуються для фільтрації повернених даних, інакше ви могли б зрештою повертати значно більше даних, ніж очікували.
Таким чином, Ви отримуєте найкраще з двох світів: анотації типів **з підтримкою інструментів** і **фільтрацію даних**.
Таким чином ви можете отримати найкраще з двох світів: анотації типів із **підтримкою інструментів** і **фільтрацію даних**.
## Подивитись у документації
## Подивитися в документації { #see-it-in-the-docs }
Коли Ви дивитесь автоматичну документацію, Ви можете побачити, що вхідна модель і вихідна модель мають власну JSON-схему:
Коли ви дивитеся автоматичну документацію, ви можете перевірити, що вхідна модель і вихідна модель матимуть власну JSON Schema:
<img src="/img/tutorial/response-model/image01.png">
І обидві моделі використовуються для інтерактивної API-документації:
І обидві моделі будуть використані для інтерактивної документації API:
<img src="/img/tutorial/response-model/image02.png">
## Інші анотації типів повернення
## Інші анотації типів повернення { #other-return-type-annotations }
Існують випадки, коли Ви повертаєте щось, що не є допустимим полем Pydantic, але анотуєте це у функції лише для того, щоб отримати підтримку від інструментів (редактора, mypy тощо).
Можуть бути випадки, коли ви повертаєте щось, що не є валідним полем Pydantic, і анотуєте це у функції лише для того, щоб отримати підтримку від інструментів (редактора, mypy тощо).
### Повернення Response напряму
### Повернути Response напряму { #return-a-response-directly }
Найпоширенішим випадком буде [повернення Response напряму, як пояснюється пізніше у розширеній документації](../advanced/response-directly.md){.internal-link target=_blank}.
{* ../../docs_src/response_model/tutorial003_02.py hl[8,10:11] *}
{* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *}
Цей простий випадок автоматично обробляється FastAPI, тому що анотація типу повернення — це клас (або підклас) `Response`.
І інструменти також будуть задоволені, бо і `RedirectResponse`, і `JSONResponse` є підкласами `Response`, отже анотація типу коректна.
### Анотація підкласу Response
### Анотувати підклас Response { #annotate-a-response-subclass }
Також можна використовувати підклас `Response` у анотації типу:
Ви також можете використати підклас `Response` в анотації типу:
{* ../../docs_src/response_model/tutorial003_03.py hl[8:9] *}
{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *}
Це теж працюватиме, бо `RedirectResponse` — підклас `Response`, і FastAPI автоматично обробить цей простий випадок.
### Некоректні анотації типу повернення
### Некоректні анотації типу повернення { #invalid-return-type-annotations }
Але коли Ви повертаєте якийсь інший довільний об’єкт, що не є валідним типом Pydantic (наприклад, об’єкт бази даних), і анотуєте його так у функції, FastAPI спробує створити Pydantic модель відповіді на основі цієї анотації типу, і це завершиться помилкою.
Але коли ви повертаєте якийсь інший довільний об’єкт, що не є валідним типом Pydantic (наприклад, об’єкт бази даних), і анотуєте його так у функції, FastAPI спробує створити модель відповіді Pydantic на основі цієї анотації типу і це завершиться помилкою.
Те саме станеться, якщо Ви використовуєте <abbr title="Об'єднання (union) кількох типів означає: «будь-який з цих типів».">union</abbr> між різними типами, де один або більше не є валідними типами Pydantic, наприклад, це спричинить помилку 💥:
Те саме станеться, якщо ви використаєте <abbr title='Обєднання (union) між кількома типами означає «будь-який із цих типів».'>union</abbr> між різними типами, де один або більше не є валідними типами Pydantic, наприклад, це завершиться помилкою 💥:
{* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *}
...це не працює, тому що тип анотації не є типом Pydantic і не є просто класом `Response` або його підкласом, а є об’єднанням (union) — або `Response`, або `dict`.
...це не працює, тому що анотація типу не є типом Pydantic і не є просто одним класом `Response` або його підкласом, це union (будь-який із двох) між `Response` і `dict`.
### Відключення Моделі Відповіді
### Вимкнути модель відповіді { #disable-response-model }
Продовжуючи приклад вище, можливо, Ви не хочете використовувати стандартну валідацію даних, автоматичну документацію, фільтрацію тощо, які FastAPI виконує за замовчуванням.
Продовжуючи приклад вище, можливо, ви не хочете мати стандартну валідацію даних, документацію, фільтрацію тощо, які виконує FastAPI.
Але ви все одно можете залишити анотацію типу у функції, щоб зберегти підтримку з боку інструментів, таких як редактори коду або статичні перевірки типів (наприклад, mypy).
Але ви можете все одно хотіти залишити анотацію типу повернення у функції, щоб отримати підтримку від інструментів, як-от редактори та перевірки типів (наприклад, mypy).
У такому випадку ви можете вимкнути генерацію моделі відповіді, встановивши `response_model=None`:
{* ../../docs_src/response_model/tutorial003_05_py310.py hl[7] *}
Це змусить FastAPI пропустити генерацію моделі відповіді, і таким чином Ви зможете використовувати будь-які анотації типів повернення без впливу на вашу FastAPI аплікацію. 🤓
Це змусить FastAPI пропустити генерацію моделі відповіді, і таким чином ви зможете використовувати будь-які потрібні анотації типів повернення без впливу на ваш FastAPI застосунок. 🤓
## Параметри кодування моделі відповіді
## Параметри кодування моделі відповіді { #response-model-encoding-parameters }
Ваша модель відповіді може мати значення за замовчуванням, наприклад:
@@ -230,19 +229,19 @@ FastAPI виконує кілька внутрішніх операцій з Pyd
* `tax: float = 10.5` має значення за замовчуванням `10.5`.
* `tags: List[str] = []` має значення за замовчуванням порожній список: `[]`.
Але Ви можете захотіти не включати їх у результат, якщо вони фактично не були збережені.
але ви можете захотіти не включати їх у результат, якщо вони фактично не були збережені.
Наприклад, якщо у Вас є моделі з багатьма необов’язковими атрибутами у NoSQL базі даних, але Ви не хочете відправляти дуже довгі JSON-відповіді, повні значень за замовчуванням.
Наприклад, якщо у вас є моделі з багатьма необов’язковими атрибутами у NoSQL базі даних, але ви не хочете надсилати дуже довгі JSON-відповіді, повні значень за замовчуванням.
### Використовуйте параметр `response_model_exclude_unset`
### Використовуйте параметр `response_model_exclude_unset` { #use-the-response-model-exclude-unset-parameter }
Ви можете встановити параметр декоратора шляху `response_model_exclude_unset=True`:
Ви можете встановити параметр *декоратора операції шляху* `response_model_exclude_unset=True`:
{* ../../docs_src/response_model/tutorial004_py310.py hl[22] *}
і ці значення за замовчуванням не будуть включені у відповідь, тільки фактично встановлені значення.
і ці значення за замовчуванням не будуть включені у відповідь, лише значення, які фактично встановлені.
Отже, якщо Ви надішлете запит до цього оператора шляху для елемента з item_id `foo`, відповідь (без включення значень за замовчуванням) буде:
Отже, якщо ви надішлете запит до цієї *операції шляху* для елемента з ID `foo`, відповідь (без включення значень за замовчуванням) буде:
```JSON
{
@@ -253,32 +252,18 @@ FastAPI виконує кілька внутрішніх операцій з Pyd
/// info | Інформація
У Pydantic версії 1 метод називався `.dict()`, він був застарілий (але ще підтримується) у Pydantic версії 2 і перейменований у `.model_dump()`.
Приклади тут використовують `.dict()` для сумісності з Pydantic v1, але Вам слід використовувати `.model_dump()`, якщо Ви можете використовувати Pydantic v2.
///
/// info | Інформація
FastAPI використовує `.dict()` моделі Pydantic з <a href="https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict" class="external-link" target="_blank">параметром `exclude_unset`</a>, щоб досягти цього.
///
/// info | Інформація
Ви також можете використовувати:
* `response_model_exclude_defaults=True`
* `response_model_exclude_none=True`
як описано в <a href="https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict" class="external-link" target="_blank">документації Pydantic</a> for `exclude_defaults` та `exclude_none`.
як описано в <a href="https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict" class="external-link" target="_blank">документації Pydantic</a> для `exclude_defaults` та `exclude_none`.
///
#### Дані зі значеннями для полів із типовими значеннями
#### Дані зі значеннями для полів із типовими значеннями { #data-with-values-for-fields-with-defaults }
Але якщо Ваші дані мають значення для полів моделі з типовими значеннями, як у елемента з item_id `bar`:
Але якщо ваші дані мають значення для полів моделі з типовими значеннями, як у елемента з ID `bar`:
```Python hl_lines="3 5"
{
@@ -288,11 +273,12 @@ FastAPI використовує `.dict()` моделі Pydantic з <a href="htt
"tax": 20.2
}
```
вони будуть включені у відповідь.
#### Дані з тими самими значеннями, що й типові
#### Дані з тими самими значеннями, що й типові { #data-with-the-same-values-as-the-defaults }
Якщо дані мають ті самі значення, що й типові, як у елемента з item_id `baz`:
Якщо дані мають ті самі значення, що й типові, як у елемента з ID `baz`:
```Python hl_lines="3 5-6"
{
@@ -304,7 +290,7 @@ FastAPI використовує `.dict()` моделі Pydantic з <a href="htt
}
```
FastAPI достатньо розумний (насправді, Pydantic достатньо розумний), щоб зрозуміти, що, хоча `description`, `tax` і `tags` мають ті самі значення, що й типові, вони були встановлені явно (а не взяті як значення за замовчуванням).
FastAPI достатньо розумний (насправді, Pydantic достатньо розумний), щоб зрозуміти, що, хоча `description`, `tax` і `tags` мають ті самі значення, що й типові, їх було встановлено явно (а не взято як значення за замовчуванням).
Отже, вони будуть включені у JSON-відповідь.
@@ -312,24 +298,23 @@ FastAPI достатньо розумний (насправді, Pydantic дос
Зверніть увагу, що типові значення можуть бути будь-якими, не лише `None`.
Це може бути list (`[]`), `float` 10.5 тощо.
Це може бути list (`[]`), `float` зі значенням `10.5` тощо.
///
### `response_model_include` та `response_model_exclude`
### `response_model_include` та `response_model_exclude` { #response-model-include-and-response-model-exclude }
Ви також можете використовувати параметри *декоратора операції шляху* `response_model_include` та `response_model_exclude`.
Вони приймають `set` (множину) рядків (`str`) з іменами атрибутів, які потрібно включити (пропускаючи інші) або виключити (включаючи інші).
Вони приймають `set` зі `str` з іменами атрибутів, які потрібно включити (пропускаючи решту) або виключити (включаючи решту).
Це можна використовувати як швидкий спосіб, якщо у Вас є лише одна модель Pydantic і Ви хочете видалити деякі дані з виводу.
Це можна використовувати як швидкий спосіб, якщо у вас є лише одна модель Pydantic і ви хочете видалити деякі дані з виводу.
/// tip | Порада
Але все ж рекомендується використовувати описані вище підходи, із застосуванням кількох класів, замість цих параметрів.
Але все ж рекомендується використовувати описані вище підходи, застосовуючи кілька класів, замість цих параметрів.
Це тому, що JSON Schema, який генерується у вашому OpenAPI додатку (і в документації), все одно буде відповідати повній моделі, навіть якщо Ви використовуєте `response_model_include` або `response_model_exclude` для виключення деяких атрибутів.
Це тому, що JSON Schema, який генерується в OpenAPI вашого застосунку (і в документації), все одно буде відповідати повній моделі, навіть якщо ви використовуєте `response_model_include` або `response_model_exclude`, щоб пропустити деякі атрибути.
Це також стосується `response_model_by_alias`, який працює подібним чином.
@@ -345,14 +330,14 @@ FastAPI достатньо розумний (насправді, Pydantic дос
///
#### Використання `list` замість `set`
#### Використання `list` замість `set` { #using-lists-instead-of-sets }
Якщо Ви забудете використати `set` і натомість застосуєте `list` або `tuple`, FastAPI все одно перетворить це на `set`, і все працюватиме правильно:
Якщо ви забудете використати `set` і натомість застосуєте `list` або `tuple`, FastAPI все одно перетворить це на `set`, і все працюватиме правильно:
{* ../../docs_src/response_model/tutorial006_py310.py hl[29,35] *}
## Підсумок
## Підсумок { #recap }
Використовуйте параметр `response_model` *декоратора операції шляху*, щоб визначати моделі відповіді, особливо щоб гарантувати фільтрацію приватних даних.
Використовуйте параметр `response_model` *декоратора операції шляху*, щоб визначати моделі відповіді і особливо щоб гарантувати фільтрацію приватних даних.
Використовуйте `response_model_exclude_unset`, щоб повертати лише явно встановлені значення.

View File

@@ -1,6 +1,6 @@
# Статус коди Відповідей
# Код статусу відповіді { #response-status-code }
Так само як Ви можете вказати модель відповіді, Ви також можете оголосити HTTP код статусу для відповіді за допомогою параметра `status_code` в будь-якій з *операцій шляху*:
Так само, як ви можете вказати модель відповіді, ви також можете оголосити HTTP код статусу, що використовується для відповіді, за допомогою параметра `status_code` в будь-якій з *операцій шляху*:
* `@app.get()`
* `@app.post()`
@@ -8,82 +8,83 @@
* `@app.delete()`
* тощо.
{* ../../docs_src/response_status_code/tutorial001.py hl[6] *}
{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *}
/// note | Нотатка
/// note | Примітка
Зверніть увагу, що `status_code` є параметром методу "декоратора" (`get`, `post` і т.д.), а не Вашої *функції операції шляху*, як усі інші параметри та тіло запиту.
Зверніть увагу, що `status_code` є параметром методу «декоратора» (`get`, `post`, тощо). Не вашої *функції операції шляху*, як усі параметри та тіло.
///
Параметр `status_code` приймає число, яке відповідає HTTP коду статусу.
Параметр `status_code` приймає число з HTTP кодом статусу.
/// info | Інформація
`status_code` також може отримувати значення з `IntEnum`, наприклад, з Python <a href="https://docs.python.org/3/library/http.html#http.HTTPStatus" class="external-link" target="_blank">`http.HTTPStatus`</a>.
`status_code` також може, як альтернативу, приймати `IntEnum`, наприклад, Python <a href="https://docs.python.org/3/library/http.html#http.HTTPStatus" class="external-link" target="_blank">`http.HTTPStatus`</a>.
///
Він буде:
* Повертати вказаний код статусу у відповіді.
* Документувати його як такий у схемі OpenAPI (і, таким чином, в інтерфейсі користувача):
* Повертати цей код статусу у відповіді.
* Документувати його як такий у схемі OpenAPI (і, таким чином, в інтерфейсах користувача):
<img src="/img/tutorial/response-status-code/image01.png">
/// note | Нотатка
/// note | Примітка
Деякі коди відповіді (див. наступний розділ) вказують, що відповідь не має тіла.
FastAPI знає про це і створить OpenAPI документацію, яка вказує, що тіла відповіді немає.
FastAPI знає про це і створить документацію OpenAPI, яка вказує, що тіла відповіді немає.
///
## Про HTTP статус коди
## Про HTTP коди статусу { #about-http-status-codes }
/// note | Нотатка
/// note | Примітка
Якщо Ви вже знаєте, що таке HTTP коди статусу, переходьте до наступного розділу.
Якщо ви вже знаєте, що таке HTTP коди статусу, перейдіть до наступного розділу.
///
В HTTP Ви надсилаєте числовий код статусу з 3 цифр як частину відповіді.
В HTTP ви надсилаєте числовий код статусу з 3 цифр як частину відповіді.
Ці коди статусу мають пов’язану назву для їх розпізнавання, але найважливішою частиною є саме число.
Ці коди статусу мають пов’язану назву для їх розпізнавання, але важливою частиною є число.
Коротко:
* **`100 - 199`** "Інформаційні" відповіді. Ви рідко використовуєте їх напряму. Відповіді з такими кодами не можуть мати тіла.
* **`200 - 299`** "Успішні" відповіді. Це ті, які Ви використовуватимете найчастіше.
* `200` - код за замовчуванням, який означає, що все пройшло "OK".
* Інший приклад `201`, "Created" (створено). Його зазвичай використовують після створення нового запису в базі даних.
* Особливий випадок `204`, "No Content" (немає вмісту). Ця відповідь використовується, коли немає даних для повернення клієнту, тому відповідь не повинна мати тіла.
* **`300 - 399`** "Перенаправлення". Відповіді з цими кодами можуть мати або не мати тіла, за винятком `304`, "Not Modified" (не змінено), яка не повинна мати тіла.
* **`400 - 499`** "Помилка клієнта". Це другий тип, який Ви, ймовірно, будете використовувати найчастіше.
* Приклад `404`, "Not Found" (не знайдено).
* Для загальних помилок клієнта можна використовувати `400`.
* `500 - 599` омилки сервера". Ви майже ніколи не використовуєте їх напряму. Якщо в коді Вашого застосунку або на сервері щось пішло не так, автоматично буде повернено один із цих кодів статусу.
* `100 - 199` — для «Information». Ви рідко використовуєте їх напряму. Відповіді з такими кодами статусу не можуть мати тіла.
* **`200 - 299`** — для «Successful» відповідей. Це ті, які ви використовуватимете найчастіше.
* `200` код статусу за замовчуванням, який означає, що все було «OK».
* Інший приклад `201`, «Created». Його зазвичай використовують після створення нового запису в базі даних.
* Особливий випадок `204`, «No Content». Цю відповідь використовують, коли немає вмісту для повернення клієнту, і тому відповідь не повинна мати тіла.
* **`300 - 399`** — для «Redirection». Відповіді з цими кодами статусу можуть мати або не мати тіла, за винятком `304`, «Not Modified», яка не повинна мати тіла.
* **`400 - 499`** — для відповідей «Client error». Це другий тип, який ви, ймовірно, будете використовувати найчастіше.
* Приклад `404`, для відповіді «Not Found».
* Для загальних помилок з боку клієнта ви можете просто використовувати `400`.
* `500 - 599` — для помилок сервера. Ви майже ніколи не використовуєте їх напряму. Коли щось піде не так у якійсь частині коду вашого застосунку або на сервері, автоматично буде повернено один із цих кодів статусу.
/// tip | Порада
Щоб дізнатися більше про кожен код статусу і призначення кожного з них, перегляньте документацію <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> про HTTP коди статусу</a>.
Щоб дізнатися більше про кожен код статусу і для чого призначений кожен із них, перегляньте документацію <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> про HTTP коди статусу</a>.
///
## Легкий спосіб запам'ятати назви
## Скорочення, щоб запамятати назви { #shortcut-to-remember-the-names }
Розглянемо ще раз попередній приклад:
Розглянемо попередній приклад ще раз:
{* ../../docs_src/response_status_code/tutorial001.py hl[6] *}
{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *}
`201` - це код статусу для "Created" (створено).
`201` це код статусу для «Created».
Але Вам не потрібно запам'ятовувати, що означає кожен із цих кодів.
Але вам не потрібно запам'ятовувати, що означає кожен із цих кодів.
Ви можете використовувати зручні змінні з `fastapi.status`
Ви можете використовувати зручні змінні з `fastapi.status`.
{* ../../docs_src/response_status_code/tutorial002.py hl[1,6] *}
{* ../../docs_src/response_status_code/tutorial002_py39.py hl[1,6] *}
Ці змінні просто для зручності. Вони містять ті ж самі числа, але Ви можете скористатися автозаповненням в редакторі:
Вони — просто для зручності, містять те саме число, але так ви можете скористатися автозаповненням редактора, щоб знайти їх:
<img src="/img/tutorial/response-status-code/image02.png">
@@ -91,10 +92,10 @@ FastAPI знає про це і створить OpenAPI документаці
Ви також можете використати `from starlette import status`.
**FastAPI** надає ті ж самі змінні `starlette.status` як `fastapi.status`, просто для зручності розробника. Однак вони походять безпосередньо зі Starlette.
**FastAPI** надає той самий `starlette.status` як `fastapi.status` просто як зручність для вас, розробника. Але він походить безпосередньо зі Starlette.
///
## Зміна значення за замовчуванням
## Зміна значення за замовчуванням { #changing-the-default }
Далі, у Посібнику для досвідчених користувачів{.internal-link target=_blank}, Ви дізнаєтесь, як повернути інший код статусу, ніж той, який Ви оголосили тут.
Пізніше, у [Посібнику для досвідчених користувачів](../advanced/response-change-status-code.md){.internal-link target=_blank}, ви побачите, як повертати інший код статусу, ніж значення за замовчуванням, яке ви оголошуєте тут.

View File

@@ -1,44 +1,22 @@
# Декларування прикладів вхідних даних
# Декларування прикладів вхідних даних { #declare-request-example-data }
Ви можете задати приклади даних, які Ваш застосунок може отримувати.
Ось кілька способів, як це зробити.
## Додаткові дані JSON-схеми в моделях Pydantic
## Додаткові дані JSON-схеми в моделях Pydantic { #extra-json-schema-data-in-pydantic-models }
Ви можете задати `examples` для моделі Pydantic, які буде додано до згенерованої JSON-схеми.
//// tab | Pydantic v2
{* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *}
////
Ця додаткова інформація буде додана як є до **JSON-схеми** для цієї моделі, і вона буде використана в документації до API.
//// tab | Pydantic v1
{* ../../docs_src/schema_extra_example/tutorial001_pv1_py310.py hl[13:23] *}
////
Ця додаткова інформація буде додана як є до **JSON-схеми**, і вона буде використовуватися в документації до API.
//// tab | Pydantic v2
У версії Pydantic 2 використовується атрибут `model_config`, який приймає `dict`, як описано в <a href="https://docs.pydantic.dev/latest/api/config/" class="external-link" target="_blank">документації Pydantic: Конфігурація</a>.
Ви можете використати атрибут `model_config`, який приймає `dict`, як описано в <a href="https://docs.pydantic.dev/latest/api/config/" class="external-link" target="_blank">документації Pydantic: Configuration</a>.
Ви можете встановити `"json_schema_extra"` як `dict`, що містить будь-які додаткові дані, які Ви хочете відобразити у згенерованій JSON-схемі, включаючи `examples`.
////
//// tab | Pydantic v1
У версії Pydantic 1 використовується внутрішній клас `Config` і параметр `schema_extra`, як описано в <a href="https://docs.pydantic.dev/1.10/usage/schema/#schema-customization" class="external-link" target="_blank">документації Pydantic: Налаштування схеми</a>.
Ви можете задати `schema_extra` як `dict`, що містить будь-які додаткові дані, які Ви хочете бачити у згенерованій JSON-схемі, включаючи `examples`.
////
/// tip | Підказка
/// tip | Порада
Ви можете використати ту ж техніку, щоб розширити JSON-схему і додати власну додаткову інформацію.
@@ -50,19 +28,19 @@
OpenAPI 3.1.0 (який використовується починаючи з FastAPI 0.99.0) додав підтримку `examples`, що є частиною стандарту **JSON-схеми**.
До цього підтримувався лише ключ `example` з одним прикладом. Він все ще підтримується в OpenAPI 3.1.0, але є застарілим і не входить до стандарту JSON Schema. Тому рекомендується перейти з `example` на `examples`. 🤓
До цього підтримувався лише ключ `example` з одним прикладом. Він все ще підтримується в OpenAPI 3.1.0, але є застарілим і не входить до стандарту JSON Schema. Тому рекомендується перейти з `example` на `examples`. 🤓
Більше про це можна прочитати в кінці цієї сторінки.
///
## Додаткові аргументи `Field`
## Додаткові аргументи `Field` { #field-additional-arguments }
Коли ви використовуєте `Field()` у моделях Pydantic, Ви також можете вказати додаткові `examples`:
{* ../../docs_src/schema_extra_example/tutorial002_py310.py hl[2,8:11] *}
## `examples` у JSON-схемі — OpenAPI
## `examples` у JSON-схемі — OpenAPI { #examples-in-json-schema-openapi }
При використанні будь-кого з наступного:
@@ -76,41 +54,41 @@ OpenAPI 3.1.0 (який використовується починаючи з F
Ви також можете задати набір `examples` з додатковою інформацією, яка буде додана до їхніх **JSON-схем** у **OpenAPI**.
### `Body` з `examples`
### `Body` з `examples` { #body-with-examples }
Тут ми передаємо `examples`, які містять один приклад очікуваних даних у `Body()`:
{* ../../docs_src/schema_extra_example/tutorial003_an_py310.py hl[22:29] *}
### Приклад у UI документації
### Приклад у UI документації { #example-in-the-docs-ui }
За допомогою будь-якого з наведених вище методів це виглядатиме так у документації за `/docs`:
За допомогою будь-якого з наведених вище методів це виглядатиме так у `/docs`:
<img src="/img/tutorial/body-fields/image01.png">
### `Body` з кількома `examples`
### `Body` з кількома `examples` { #body-with-multiple-examples }
Звичайно, Ви також можете передати кілька `examples`:
{* ../../docs_src/schema_extra_example/tutorial004_an_py310.py hl[23:38] *}
Коли Ви це робите, приклади будуть частиною внутрішньої **JSON-схеми** для цих даних.
Коли Ви це робите, приклади будуть частиною внутрішньої **JSON-схеми** для цих даних тіла.
Втім, на момент написання цього (<abbr title="2023-08-26">26 серпня 2023</abbr>), Swagger UI — інструмент, який відповідає за відображення UI документації — не підтримує показ кількох прикладів у **JSON-схеми**. Але нижче можна прочитати про обхідний шлях.
Втім, на момент написання цього (<abbr title="2023-08-26">час написання цього</abbr>), Swagger UI — інструмент, який відповідає за відображення UI документації — не підтримує показ кількох прикладів для даних у **JSON-схемі**. Але нижче можна прочитати про обхідний шлях.
### Специфічні для OpenAPI `examples`
### Специфічні для OpenAPI `examples` { #openapi-specific-examples }
Ще до того, як **JSON-схема** почала підтримувати `examples`, OpenAPI вже мала підтримку поля з такою ж назвою — `examples`.
Ще до того, як **JSON-схема** почала підтримувати `examples`, OpenAPI вже мала підтримку іншого поля, яке також називається `examples`.
Це **специфічне для OpenAPI** поле `examples` розміщується в іншій частині специфікації OpenAPIу **деталях кожної *операції шляху***, а не всередині самої JSON-схеми.
Це **специфічне для OpenAPI** поле `examples` розміщується в іншому розділі специфікації OpenAPI. Воно розміщується в **деталях кожної *операції шляху***, а не всередині кожної JSON-схеми.
Swagger UI вже давно підтримує це поле `examples`. Тому Ви можете використовувати його, щоб **відображати** кілька **прикладів у документації**.
І Swagger UI вже давно підтримує це поле `examples`. Тому Ви можете використовувати його, щоб **відображати** різні **приклади в UI документації**.
Це поле `examples` у специфікації OpenAPI — це `dict` (словник) з **кількома прикладами** (а не список `list`), кожен із яких може містити додаткову інформацію, що буде додана до **OpenAPI**.
Форма цього специфічного для OpenAPI поля `examples` — це `dict` з **кількома прикладами** (а не `list`), кожен із яких має додаткову інформацію, яка також буде додана до **OpenAPI**.
Воно не включається до JSON Schema кожного параметра, а розміщується зовні, безпосередньо в *операції шляху*.
Воно не включається всередину кожної JSON-схеми, що міститься в OpenAPI, воно розміщується зовні, безпосередньо в *операції шляху*.
### Використання параметра `openapi_examples`
### Використання параметра `openapi_examples` { #using-the-openapi-examples-parameter }
Ви можете оголосити специфічні для OpenAPI `examples` у FastAPI за допомогою параметра `openapi_examples` для:
@@ -122,30 +100,32 @@ Swagger UI вже давно підтримує це поле `examples`. Том
* `Form()`
* `File()`
Ключі словника (`dict`) ідентифікують кожен приклад, а кожне значення `dict` — кожен специфічний словник `dict` в `examples` може містити:
Ключі `dict` ідентифікують кожен приклад, а кожне значення — це інший `dict`.
Кожен специфічний `dict` прикладу в `examples` може містити:
* `summary`: короткий опис прикладу.
* `description`: розгорнутий опис (може містити Markdown).
* `value`: сам приклад, наприклад, словник (`dict`).
* `externalValue`: альтернатива `value`, URL-адреса, що вказує на приклад. Проте ця опція може не підтримуватися більшістю інструментів, на відміну від `value`.
* `description`: розгорнутий опис, який може містити Markdown.
* `value`: це сам приклад, який буде показано, наприклад `dict`.
* `externalValue`: альтернатива `value`, URL-адреса, що вказує на приклад. Проте це може не підтримуватися такою кількістю інструментів, як `value`.
Використання виглядає так:
{* ../../docs_src/schema_extra_example/tutorial005_an_py310.py hl[23:49] *}
### Приклади OpenAPI у UI документації
### Приклади OpenAPI в UI документації { #openapi-examples-in-the-docs-ui }
З параметром `openapi_examples`, доданим до `Body()`, документація `/docs` виглядатиме так:
З `openapi_examples`, доданим до `Body()`, `/docs` виглядатиме так:
<img src="/img/tutorial/body-fields/image02.png">
## Технічні деталі
## Технічні деталі { #technical-details }
/// tip | Підказка
/// tip | Порада
Якщо Ви вже використовуєте **FastAPI** версії **0.99.0 або вище**, Ви можете **пропустити** цей розділ.
Якщо Ви вже використовуєте **FastAPI** версії **0.99.0 або вище**, Ви, ймовірно, можете **пропустити** ці технічні деталі.
Він більш актуальний для старих версій, до появи OpenAPI 3.1.0.
Вони більш актуальні для старих версій, до появи OpenAPI 3.1.0.
Можна вважати це коротким **історичним екскурсом** у OpenAPI та JSON Schema. 🤓
@@ -155,68 +135,68 @@ Swagger UI вже давно підтримує це поле `examples`. Том
Це дуже технічна інформація про стандарти **JSON Schema** і **OpenAPI**.
Якщо вищезгадані ідеї вже працюють у Вас — можете не заглиблюватися в ці деталі.
Якщо вищезгадані ідеї вже працюють у Вас, цього може бути достатньо, і Вам, ймовірно, не потрібні ці деталі — можете пропустити.
///
До OpenAPI 3.1.0 специфікація використовувала стару та модифіковану версію **JSON Schema**.
До OpenAPI 3.1.0 OpenAPI використовував стару та модифіковану версію **JSON Schema**.
Оскільки JSON Schema раніше не підтримувала `examples`, OpenAPI додала власне поле `examples`.
JSON Schema не мала `examples`, тож OpenAPI додала власне поле `example` до своєї модифікованої версії.
OpenAPI також додала `example` і `examples` до інших частин специфікації:
OpenAPI також додала поля `example` і `examples` до інших частин специфікації:
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#parameter-object" class="external-link" target="_blank">`Parameter Object` (в специфікації)</a> використовується FastAPI для:
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#parameter-object" class="external-link" target="_blank">`Parameter Object` (в специфікації)</a>, який використовувався утилітами FastAPI:
* `Path()`
* `Query()`
* `Header()`
* `Cookie()`
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#media-type-object" class="external-link" target="_blank">`Request Body Object`, в полі `content`, в `Media Type Object` (в специфікації)</a> використовується FastAPI для:
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#media-type-object" class="external-link" target="_blank">`Request Body Object`, у полі `content`, у `Media Type Object` (в специфікації)</a>, який використовувався утилітами FastAPI:
* `Body()`
* `File()`
* `Form()`
/// info | Інформація
Цей старий параметр `examples`, специфічний для OpenAPI, тепер називається `openapi_examples`, починаючи з FastAPI версії `0.103.0`.
Цей старий специфічний для OpenAPI параметр `examples` тепер називається `openapi_examples`, починаючи з FastAPI `0.103.0`.
///
### Поле `examples` у JSON Schema
### Поле `examples` у JSON Schema { #json-schemas-examples-field }
Пізніше JSON Schema додала поле <a href="https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.5" class="external-link" target="_blank">`examples`</a> у нову версію специфікації.
І вже OpenAPI 3.1.0 базується на цій новій версії (JSON Schema 2020-12), яка включає поле `examples`.
А потім новий OpenAPI 3.1.0 базувався на найновішій версії (JSON Schema 2020-12), яка включала це нове поле `examples`.
Тепер це поле `examples` є пріоритетним і замінює старе (і кастомне) поле `example`, яке стало застарілим.
І тепер це нове поле `examples` має вищий пріоритет за старе одиночне (і кастомне) поле `example`, яке тепер є застарілим.
Нове поле `examples` у JSON Schema — це **просто список (`list`)** прикладів, без додаткових метаданих (на відміну від OpenAPI).
Це нове поле `examples` у JSON Schema — це **просто `list`** прикладів, а не `dict` з додатковими метаданими, як в інших місцях OpenAPI (описаних вище).
/// info | Інформація
Навіть після того, як з'явився OpenAPI 3.1.0, який підтримував examples у JSON Schema, інструмент Swagger UI ще деякий час не підтримував цю версію (підтримка з’явилась з версії 5.0.0 🎉).
Навіть після релізу OpenAPI 3.1.0 з цією новою простішою інтеграцією з JSON Schema, протягом певного часу Swagger UI, інструмент, який надає автоматичну документацію, не підтримував OpenAPI 3.1.0 (тепер підтримує, починаючи з версії 5.0.0 🎉).
Через це версії FastAPI до 0.99.0 все ще використовували версії OpenAPI нижчі за 3.1.0.
///
### `Examples` в Pydantic і FastAPI
### `examples` у Pydantic і FastAPI { #pydantic-and-fastapi-examples }
Коли Ви додаєте `examples` у модель Pydantic через `schema_extra` або `Field(examples=["something"])`, ці приклади додаються до **JSON Schema** цієї моделі.
Коли Ви додаєте `examples` у модель Pydantic через `schema_extra` або `Field(examples=["something"])`, цей приклад додається до **JSON Schema** для цієї моделі Pydantic.
І ця **JSON Schema** Pydantic-моделі включається до **OpenAPI** Вашого API, а потім використовується в UI документації (docs UI).
І ця **JSON Schema** Pydantic-моделі включається до **OpenAPI** Вашого API, а потім використовується в UI документації.
У версіях FastAPI до 0.99.0 (починаючи з 0.99.0 використовується новіший OpenAPI 3.1.0), коли Ви використовували `example` або `examples` з іншими утилітами (`Query()`, `Body()` тощо), ці приклади не додавалися до JSON Schema, який описує ці дані (навіть не до власної версії JSON Schema у OpenAPI). Натомість вони додавалися безпосередньо до опису *обробника шляху* *(path operation)* в OpenAPI (тобто поза межами частин, які використовують JSON Schema).
У версіях FastAPI до 0.99.0 (0.99.0 і вище використовують новіший OpenAPI 3.1.0), коли Ви використовували `example` або `examples` з будь-якими іншими утилітами (`Query()`, `Body()` тощо), ці приклади не додавалися до JSON Schema, що описує ці дані (навіть не до власної версії JSON Schema в OpenAPI), натомість вони додавалися безпосередньо до декларації *операції шляху* в OpenAPI (поза межами частин OpenAPI, які використовують JSON Schema).
Але тепер, коли FastAPI 0.99.0 і вище використовують OpenAPI 3.1.0, а той — JSON Schema 2020-12, разом із Swagger UI 5.0.0 і вище все стало більш узгодженим, і examples тепер включаються до JSON Schema.
Але тепер, коли FastAPI 0.99.0 і вище використовує OpenAPI 3.1.0, який використовує JSON Schema 2020-12, і Swagger UI 5.0.0 і вище, все стало більш узгодженим, і приклади включаються до JSON Schema.
### Swagger UI та специфічні для OpenAPI `examples`
### Swagger UI та специфічні для OpenAPI `examples` { #swagger-ui-and-openapi-specific-examples }
Раніше (станом на 26 серпня 2023 року) Swagger UI не підтримував кілька прикладів у JSON Schema, тому користувачі не мали можливості показати декілька прикладів у документації.
Оскільки Swagger UI не підтримував кілька прикладів JSON Schema (станом на 2023-08-26), користувачі не мали можливості показати кілька прикладів у документації.
Щоб вирішити це, FastAPI починаючи з версії 0.103.0 **додав підтримку** старого **OpenAPI-специфічного** поля `examples` через новий параметр `openapi_examples`. 🤓
Щоб вирішити це, FastAPI `0.103.0` **додав підтримку** оголошення того самого старого **OpenAPI-специфічного** поля `examples` через новий параметр `openapi_examples`. 🤓
### Підсумок
### Підсумок { #summary }
Раніше я казав, що не люблю історію... а тепер ось я — розповідаю "технічні історичні" лекції. 😅
Раніше я казав, що не дуже люблю історію... а тепер подивіться на мене — читаю «технічні історичні» лекції. 😅
Коротко: **оновіться до FastAPI 0.99.0 або вище**і все стане значно **простішим, узгодженим та інтуїтивно зрозумілим**, і Вам не доведеться знати всі ці історичні деталі. 😎

View File

@@ -1,70 +1,72 @@
# Безпека
# Безпека { #security }
Існує багато способів реалізувати безпеку, автентифікацію та авторизацію.
Це зазвичай складна і "непроста" тема.
І зазвичай це складна і «непроста» тема.
У багатьох фреймворках і системах забезпечення безпеки та автентифікації займає величезну частину зусиль і коду (іноді — понад 50% всього написаного коду).
У багатьох фреймворках і системах лише обробка безпеки та автентифікації потребує великих зусиль і коду (у багатьох випадках це може бути 50% або більше від усього написаного коду).
**FastAPI** надає кілька інструментів, які допоможуть Вам впоратися з **безпекою** легко, швидко, стандартним способом, без необхідності вивчати всі специфікації безпеки.
**FastAPI** надає кілька інструментів, які допоможуть вам працювати з **безпекою** легко, швидко, стандартним способом, без необхідності вивчати всі специфікації безпеки.
Але спочатку кілька коротких понять.
Але спочатку розгляньмо кілька невеликих понять.
## Поспішаєте?
## Поспішаєте? { #in-a-hurry }
Якщо Вам не цікаві всі ці терміни й просто потрібно *швидко* додати автентифікацію за логіном і паролем — переходьте до наступних розділів.
Якщо вам не цікаві всі ці терміни й вам просто потрібно додати безпеку з автентифікацією на основі імені користувача та пароля *прямо зараз*, переходьте до наступних розділів.
## OAuth2
## OAuth2 { #oauth2 }
OAuth2 — це специфікація, що описує кілька способів обробки автентифікації та авторизації.
OAuth2 — це специфікація, що визначає кілька способів обробки автентифікації та авторизації.
Це досить об'ємна специфікація, яка охоплює складні випадки використання.
Це досить об'ємна специфікація, яка охоплює кілька складних випадків використання.
Вона включає способи автентифікації через "третю сторону".
Вона включає способи автентифікації через «третю сторону».
Саме це лежить в основі "входу через Google, Facebook, X (Twitter), GitHub" тощо.
Саме це лежить в основі всіх систем із «увійти через Facebook, Google, X (Twitter), GitHub».
### OAuth 1
### 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 }
OpenID Connect — ще одна специфікація, побудована на основі **OAuth2**.
Вона розширює OAuth2, уточнюючи деякі неоднозначності для досягнення кращої сумісності.
Вона просто розширює OAuth2, уточнюючи деякі відносно неоднозначні речі в OAuth2, щоб зробити його більш сумісним.
Наприклад, вхід через Google використовує OpenID Connect (який базується на OAuth2).
Наприклад, вхід через Google використовує OpenID Connect (який під капотом використовує OAuth2).
Але вхід через Facebook — ні. Він має власну реалізацію на базі OAuth2.
Але вхід через Facebook не підтримує OpenID Connect. Він має власний різновид OAuth2.
### OpenID (не "OpenID Connect")
### OpenID (не «OpenID Connect») { #openid-not-openid-connect }
Існувала також специфікація "OpenID", яка намагалася розвʼязати ті самі задачі, що й **OpenID Connect**, але не базувалась на OAuth2.
Існувала також специфікація «OpenID». Вона намагалася розвʼязати те саме, що й **OpenID Connect**, але не базувалась на OAuth2.
Це була зовсім інша система, і сьогодні вона майже не використовується.
Тож це була повністю додаткова система.
## OpenAPI
Зараз вона не дуже популярна або використовується.
OpenAPI (раніше Swagger) — це специфікація для побудови API (тепер під егідою Linux Foundation).
## OpenAPI { #openapi }
OpenAPI (раніше відомий як Swagger) — це відкрита специфікація для побудови API (тепер частина Linux Foundation).
**FastAPI** базується на **OpenAPI**.
Завдяки цьому Ви отримуєте автоматичну інтерактивну документацію, генерацію коду та багато іншого.
Саме це робить можливими кілька автоматичних інтерактивних інтерфейсів документації, генерацію коду тощо.
OpenAPI дозволяє описувати різні "схеми" безпеки.
OpenAPI має спосіб визначати різні «схеми» безпеки.
Використовуючи їх, Ви можете скористатися всіма цими інструментами, що базуються на стандартах, зокрема інтерактивними системами документації.
Використовуючи їх, ви можете скористатися всіма цими інструментами, що базуються на стандартах, зокрема цими інтерактивними системами документації.
OpenAPI визначає такі схеми безпеки:
@@ -72,33 +74,33 @@ OpenAPI визначає такі схеми безпеки:
* Параметр запиту.
* Заголовок.
* Cookie.
* `http`: стандартні методи HTTP-автентифікації, включаючи:
* `bearer`: заголовок `Authorization` зі значенням `Bearer` та токеном. Це успадковано з OAuth2.
* HTTP Basic автентифікація
* HTTP Digest, тощо.
* `http`: стандартні системи HTTP-автентифікації, включаючи:
* `bearer`: заголовок `Authorization` зі значенням `Bearer ` та токеном. Це успадковано з OAuth2.
* HTTP Basic автентифікацію.
* HTTP Digest тощо.
* `oauth2`: усі способи обробки безпеки за допомогою OAuth2 (так звані «потоки»).
* Деякі з цих потоків підходять для створення власного провайдера автентифікації OAuth 2.0 (наприклад, Google, Facebook, X (Twitter), GitHub тощо):
* `implicit`— неявний
* `clientCredentials`— облікові дані клієнта
* `authorizationCode` — код авторизації
* Але є один окремий «потік», який ідеально підходить для реалізації автентифікації всередині одного додатку:
* `password`: у наступних розділах буде приклад використання цього потоку.
* `openIdConnect`: дозволяє автоматично виявляти параметри автентифікації OAuth2.
* Це автоматичне виявлення визначається у специфікації OpenID Connect.
* Декілька з цих потоків підходять для створення провайдера автентифікації OAuth 2.0 (наприклад, Google, Facebook, X (Twitter), GitHub тощо):
* `implicit`
* `clientCredentials`
* `authorizationCode`
* Але є один окремий «потік», який можна ідеально використати для обробки автентифікації напряму в цьому ж застосунку:
* `password`: у кількох наступних розділах будуть приклади цього.
* `openIdConnect`: має спосіб визначити, як автоматично виявляти дані автентифікації OAuth2.
* Саме це автоматичне виявлення визначено у специфікації OpenID Connect.
/// tip | Порада
Інтеграція інших провайдерів автентифікації/авторизації, таких як Google, Facebook, X (Twitter), GitHub тощо також можлива і відносно проста.
Інтеграція інших провайдерів автентифікації/авторизації, таких як Google, Facebook, X (Twitter), GitHub тощо, також можлива і відносно проста.
Найскладніше — це створити власного провайдера автентифікації/авторизації, як Google чи Facebook. Але **FastAPI** надає Вам інструменти, щоб зробити це легко, беручи на себе важку частину роботи.
Найскладніше — це створити провайдера автентифікації/авторизації на кшталт таких, але **FastAPI** надає вам інструменти, щоб зробити це легко, виконуючи важку частину роботи за вас.
///
## Інструменти **FastAPI**
## Утиліти **FastAPI** { #fastapi-utilities }
FastAPI надає кілька інструментів для кожної з описаних схем безпеки в модулі `fastapi.security`, які спрощують використання цих механізмів захисту.
FastAPI надає кілька інструментів для кожної з описаних схем безпеки в модулі `fastapi.security`, які спрощують використання цих механізмів безпеки.
У наступних розділах Ви побачите, як додати безпеку до свого API за допомогою цих інструментів **FastAPI**.
У наступних розділах ви побачите, як додати безпеку до свого API за допомогою цих інструментів, які надає **FastAPI**.
А також побачите, як вона автоматично інтегрується в інтерактивну документацію вашого API.
А також побачите, як це автоматично інтегрується в інтерактивну систему документації.

View File

@@ -1,13 +1,13 @@
# Статичні файли
# Статичні файли { #static-files }
Ви можете автоматично надавати статичні файли з каталогу, використовуючи `StaticFiles`.
## Використання `StaticFiles`
## Використання `StaticFiles` { #use-staticfiles }
* Імпортуйте `StaticFiles`.
* "Під'єднати" екземпляр `StaticFiles()` з вказанням необхідного шляху.
* «Під'єднати» екземпляр `StaticFiles()` з вказанням необхідного шляху.
{* ../../docs_src/static_files/tutorial001.py hl[2,6] *}
{* ../../docs_src/static_files/tutorial001_py39.py hl[2,6] *}
/// note | Технічні деталі
@@ -17,24 +17,24 @@
///
### Що таке "Під'єднання"
### Що таке «Під'єднання» { #what-is-mounting }
"Під'єднання" означає додавання повноцінного "незалежного" застосунку за певним шляхом, який потім обробляє всі під шляхи.
«Під'єднання» означає додавання повноцінного «незалежного» застосунку за певним шляхом, який потім обробляє всі під шляхи.
Це відрізняється від використання `APIRouter`, оскільки під'єднаний застосунок є повністю незалежним. OpenAPI та документація вашого основного застосунку не будуть знати нічого про ваш під'єднаний застосунок.
Це відрізняється від використання `APIRouter`, оскільки під'єднаний застосунок є повністю незалежним. OpenAPI та документація вашого основного застосунку не будуть знати нічого про ваш під'єднаний застосунок тощо.
Ви можете дізнатися більше про це в [Посібнику для просунутих користувачів](../advanced/index.md){.internal-link target=_blank}.
## Деталі
## Деталі { #details }
Перше `"/static"` вказує на під шлях, за яким буде "під'єднано" цей новий "застосунок". Тому будь-який шлях, який починається з `"/static"`, буде оброблятися ним.
Перше `"/static"` вказує на під шлях, за яким буде «під'єднано» цей новий «підзастосунок». Тому будь-який шлях, який починається з `"/static"`, буде оброблятися ним.
`directory="static"` визначає каталог, що містить ваші статичні файли.
`directory="static"` визначає назву каталогу, що містить ваші статичні файли.
`name="static"` це ім'я, яке можна використовувати всередині **FastAPI**.
Усі ці параметри можуть бути змінені відповідно до потреб і особливостей вашого застосунку.
Усі ці параметри можуть бути іншими за "`static`", налаштуйте їх відповідно до потреб і особливостей вашого застосунку.
## Додаткова інформація
## Додаткова інформація { #more-info }
Детальніше про налаштування та можливості можна дізнатися в <a href="https://www.starlette.dev/staticfiles/" class="external-link" target="_blank">документації Starlette про статичні файли</a>.

View File

@@ -1,17 +1,18 @@
# Тестування
# Тестування { #testing }
Тестування **FastAPI** додатків є простим та ефективним завдяки бібліотеці <a href="https://www.starlette.dev/testclient/" class="external-link" target="_blank">Starlette</a>, яка базується на <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a>.
Оскільки HTTPX розроблений на основі Requests, його API є інтуїтивно зрозумілим для тих, хто вже знайомий з Requests.
Завдяки <a href="https://www.starlette.dev/testclient/" class="external-link" target="_blank">Starlette</a> тестувати застосунки **FastAPI** просто й приємно.
З його допомогою Ви можете використовувати <a href="https://docs.pytest.org/" class="external-link" target="_blank">pytest</a> безпосередньо з **FastAPI**.
Воно базується на <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a>, який, своєю чергою, спроєктований на основі Requests, тож він дуже знайомий та інтуїтивно зрозумілий.
## Використання `TestClient`
З його допомогою ви можете використовувати <a href="https://docs.pytest.org/" class="external-link" target="_blank">pytest</a> безпосередньо з **FastAPI**.
## Використання `TestClient` { #using-testclient }
/// info | Інформація
Щоб використовувати `TestClient`, спочатку встановіть <a href="https://www.python-httpx.org" class="external-link" target="_blank">`httpx`</a>.
Переконайтеся, що Ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його, а потім встановили саму бібліотеку, наприклад:
Переконайтеся, що ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його, а потім встановили `httpx`, наприклад:
```console
$ pip install httpx
@@ -21,7 +22,7 @@ $ pip install httpx
Імпортуйте `TestClient`.
Створіть `TestClient`, передавши йому Ваш застосунок **FastAPI**.
Створіть `TestClient`, передавши йому ваш застосунок **FastAPI**.
Створюйте функції з іменами, що починаються з `test_` (це стандартна угода для `pytest`).
@@ -29,8 +30,7 @@ $ pip install httpx
Записуйте прості `assert`-вирази зі стандартними виразами Python, які потрібно перевірити (це також стандарт для `pytest`).
{* ../../docs_src/app_testing/tutorial001.py hl[2,12,15:18] *}
{* ../../docs_src/app_testing/tutorial001_py39.py hl[2,12,15:18] *}
/// tip | Порада
@@ -46,25 +46,25 @@ $ pip install httpx
Ви також можете використовувати `from starlette.testclient import TestClient`.
**FastAPI** надає той самий `starlette.testclient` під назвою `fastapi.testclient` для зручності розробників, але він безпосередньо походить із Starlette.
**FastAPI** надає той самий `starlette.testclient` під назвою `fastapi.testclient` просто для зручності для вас, розробника. Але він безпосередньо походить із Starlette.
///
/// tip | Порада
Якщо Вам потрібно викликати `async`-функції у ваших тестах, окрім відправлення запитів до FastAPI-застосунку (наприклад, асинхронні функції роботи з базою даних), перегляньте [Асинхронні тести](../advanced/async-tests.md){.internal-link target=_blank} у розширеному керівництві.
Якщо ви хочете викликати `async`-функції у ваших тестах, окрім відправлення запитів до вашого застосунку FastAPI (наприклад, асинхронні функції роботи з базою даних), перегляньте [Async Tests](../advanced/async-tests.md){.internal-link target=_blank} у розширеному керівництві.
///
## Розділення тестів
## Розділення тестів { #separating-tests }
У реальному застосунку Ваші тести, ймовірно, будуть в окремому файлі.
У реальному застосунку ваші тести, ймовірно, будуть в окремому файлі.
Також Ваш **FastAPI**-застосунок може складатися з кількох файлів або модулів тощо.
Також ваш застосунок **FastAPI** може складатися з кількох файлів/модулів тощо.
### Файл застосунку **FastAPI**
### Файл застосунку **FastAPI** { #fastapi-app-file }
Припустимо, у Вас є структура файлів, описана в розділі [Більші застосунки](bigger-applications.md){.internal-link target=_blank}:
Припустимо, у вас є структура файлів, описана в розділі [Bigger Applications](bigger-applications.md){.internal-link target=_blank}:
```
.
@@ -72,14 +72,15 @@ $ pip install httpx
│   ├── __init__.py
│   └── main.py
```
У файлі `main.py` знаходиться Ваш застосунок **FastAPI** :
{* ../../docs_src/app_testing/main.py *}
У файлі `main.py` знаходиться ваш застосунок **FastAPI**:
### Файл тестування
Ви можете створити файл `test_main.py` з Вашими тестами. Він може знаходитися в тому ж пакеті Python (у тій самій директорії з файлом `__init__.py`):
{* ../../docs_src/app_testing/app_a_py39/main.py *}
### Файл тестування { #testing-file }
Ви можете створити файл `test_main.py` з вашими тестами. Він може знаходитися в тому ж пакеті Python (у тій самій директорії з файлом `__init__.py`):
``` hl_lines="5"
.
@@ -89,18 +90,18 @@ $ pip install httpx
│   └── test_main.py
```
Оскільки цей файл знаходиться в тому ж пакеті, Ви можете використовувати відносний імпорт, щоб імпортувати об'єкт `app` із модуля `main` (`main.py`):
Оскільки цей файл знаходиться в тому ж пакеті, ви можете використовувати відносний імпорт, щоб імпортувати об'єкт `app` із модуля `main` (`main.py`):
{* ../../docs_src/app_testing/test_main.py hl[3] *}
{* ../../docs_src/app_testing/app_a_py39/test_main.py hl[3] *}
...і написати код для тестів так само як і раніше.
## Тестування: розширений приклад
## Тестування: розширений приклад { #testing-extended-example }
Тепер розширимо цей приклад і додамо більше деталей, щоб побачити, як тестувати різні частини.
### Розширений файл застосунку **FastAPI**
### Розширений файл застосунку **FastAPI** { #extended-fastapi-app-file }
Залишимо ту саму структуру файлів:
@@ -112,75 +113,26 @@ $ pip install httpx
│   └── test_main.py
```
Припустимо, що тепер файл `main.py` із Вашим **FastAPI**-застосунком містить додаткові операції шляху (**path operations**).
Припустимо, що тепер файл `main.py` із вашим застосунком **FastAPI** містить інші **операції шляху**.
Він має `GET`-операцію, яка може повертати помилку.
Він має `POST`-операцію, яка може повертати кілька помилок.
Обидві операції шляху вимагають заголовок `X-Token`.
Обидві *операції шляху* вимагають заголовок `X-Token`.
//// tab | Python 3.10+
{* ../../docs_src/app_testing/app_b_an_py310/main.py *}
```Python
{!> ../../docs_src/app_testing/app_b_an_py310/main.py!}
```
### Розширений тестовий файл { #extended-testing-file }
////
Потім ви можете оновити `test_main.py`, додавши розширені тести:
//// tab | Python 3.9+
{* ../../docs_src/app_testing/app_b_an_py310/test_main.py *}
```Python
{!> ../../docs_src/app_testing/app_b_an_py39/main.py!}
```
////
Коли вам потрібно передати клієнту інформацію в запиті, але ви не знаєте, як це зробити, ви можете пошукати (Google), як це зробити в `httpx`, або навіть як це зробити з `requests`, оскільки дизайн HTTPX базується на дизайні Requests.
//// tab | Python 3.8+
```Python
{!> ../../docs_src/app_testing/app_b_an/main.py!}
```
////
//// tab | Python 3.10+ non-Annotated
/// tip | Порада
Бажано використовувати версію з `Annotated`, якщо це можливо
///
```Python
{!> ../../docs_src/app_testing/app_b_py310/main.py!}
```
////
//// tab | Python 3.8+ non-Annotated
/// tip | Порада
Бажано використовувати версію з `Annotated`, якщо це можливо
///
```Python
{!> ../../docs_src/app_testing/app_b/main.py!}
```
////
### Розширений тестовий файл
Потім Ви можете оновити `test_main.py`, додавши розширені тести:
{* ../../docs_src/app_testing/app_b/test_main.py *}
Коли Вам потрібно передати клієнту інформацію в запиті, але Ви не знаєте, як це зробити, Ви можете пошукати (наприклад, у Google) спосіб реалізації в `httpx`, або навіть у `requests`, оскільки HTTPX розроблений на основі дизайну Requests.
Далі Ви просто повторюєте ці ж дії у ваших тестах.
Далі ви просто повторюєте ці ж дії у ваших тестах.
Наприклад:
@@ -195,15 +147,16 @@ $ pip install httpx
/// info | Інформація
Зверніть увагу, що `TestClient` отримує дані, які можна конвертувати в JSON, а не Pydantic-моделі.
Якщо у Вас є Pydantic-модель у тесті, і Ви хочете передати її дані в додаток під час тестування, Ви можете використати `jsonable_encoder`, описаний у розділі [JSON Compatible Encoder](encoder.md){.internal-link target=_blank}.
Якщо у вас є Pydantic-модель у тесті, і ви хочете передати її дані в застосунок під час тестування, ви можете використати `jsonable_encoder`, описаний у розділі [JSON Compatible Encoder](encoder.md){.internal-link target=_blank}.
///
## Запуск тестів
## Запуск { #run-it }
Після цього вам потрібно встановити `pytest`.
Переконайтеся, що Ви створили [віртуальне середовище]{.internal-link target=_blank}, активували його і встановили необхідні пакети, наприклад:
Переконайтеся, що ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його і встановили необхідні пакети, наприклад:
<div class="termy">
@@ -215,7 +168,7 @@ $ pip install pytest
</div>
`pytest` автоматично знайде файли з тестами, виконає їх і надасть вам результати.
Він автоматично знайде файли та тести, виконає їх і повідомить вам результати.
Запустіть тести за допомогою: