mirror of
https://github.com/fastapi/fastapi.git
synced 2025-12-23 22:29:34 -05:00
🌐 Update translations for uk (update-outdated)
This commit is contained in:
@@ -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>):
|
||||
|
||||

|
||||
|
||||
### Альтернативні документації 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>):
|
||||
|
||||

|
||||
|
||||
## Приклад оновлення
|
||||
## Приклад оновлення { #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 буде автоматично оновлена, включно з новим тілом:
|
||||
|
||||

|
||||
|
||||
* Натисніть кнопку "Try it out", це дозволить вам заповнити параметри та безпосередньо взаємодіяти з API:
|
||||
* Натисніть кнопку "Try it out", вона дозволяє заповнити параметри та безпосередньо взаємодіяти з API:
|
||||
|
||||

|
||||
|
||||
* Потім натисніть кнопку "Execute", інтерфейс користувача зв'яжеться з вашим API, надішле параметри, у відповідь отримає результати та покаже їх на екрані:
|
||||
* Потім натисніть кнопку "Execute", інтерфейс користувача зв'яжеться з вашим API, надішле параметри, отримає результати та покаже їх на екрані:
|
||||
|
||||

|
||||
|
||||
### Оновлення альтернативної 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>.
|
||||
|
||||
* Альтернативна документація також показуватиме новий параметр і вміст запиту:
|
||||
* Альтернативна документація також відобразить новий параметр запиту та тіло:
|
||||
|
||||

|
||||
|
||||
### Підсумки
|
||||
### Підсумки { #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 ...
|
||||
```
|
||||
|
||||
...і побачите, як ваш редактор автоматично заповнюватиме атрибути та знатиме їхні типи:
|
||||
...і побачите, як ваш редактор автоматично доповнюватиме атрибути та знатиме їхні типи:
|
||||
|
||||

|
||||
|
||||
Для більш повного ознайомлення з додатковими функціями, перегляньте <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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Навчання
|
||||
# Навчання { #learn }
|
||||
|
||||
У цьому розділі надані вступні та навчальні матеріали для вивчення FastAPI.
|
||||
У цьому розділі надані вступні розділи та навчальні матеріали для вивчення **FastAPI**.
|
||||
|
||||
Це можна розглядати як **книгу**, **курс**, або **офіційний** та рекомендований спосіб освоїти FastAPI. 😎
|
||||
|
||||
@@ -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>.
|
||||
|
||||
///
|
||||
|
||||
@@ -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` як параметри у *функціях операції шляху* та залежностях, щоб додавати фонові задачі.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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** вбудовувати тіло в ключ, навіть коли оголошено лише один параметр.
|
||||
|
||||
@@ -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, зберігаючи при цьому код простим, коротким та елегантним.
|
||||
|
||||
А також отримуєте всі переваги:
|
||||
|
||||
* Підтримка в редакторі (автодоповнення всюди!)
|
||||
* Конвертація даних (парсинг/сериалізація)
|
||||
* Валідація даних
|
||||
* Валідацію даних
|
||||
* Документація схем
|
||||
* Автоматичне створення документації
|
||||
|
||||
@@ -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}.
|
||||
|
||||
|
||||
@@ -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}.
|
||||
|
||||
@@ -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**. 😎
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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 | Технічні деталі
|
||||
|
||||
|
||||
@@ -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**, зупиниться на точках зупину тощо.
|
||||
|
||||
Ось як це може виглядати:
|
||||
|
||||
|
||||
@@ -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 | Примітка
|
||||
|
||||
|
||||
@@ -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] *}
|
||||
|
||||
|
||||
@@ -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: ['/home/user/code/awesomeapp']
|
||||
<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">'/home/user/code/awesomeapp'</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>):
|
||||
|
||||

|
||||
|
||||
### Альтернативна 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>):
|
||||
|
||||

|
||||
|
||||
### 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`.
|
||||
|
||||
@@ -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` для виведення дуже інформативного повідомлення, але Ви зрозуміли основну ідею. Ви можете обробити помилку та повторно використовувати обробники помилок за замовчуванням.
|
||||
У цьому прикладі ви просто друкуєте помилку з дуже виразним повідомленням, але ви зрозуміли основну ідею. Ви можете використовувати виключення, а потім просто повторно використати обробники виключень за замовчуванням.
|
||||
|
||||
@@ -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**. 😎
|
||||
|
||||
@@ -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** подбає про їх перетворення.
|
||||
|
||||
@@ -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">'/home/user/code/awesomeapp'</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]"
|
||||
|
||||
Але вам слід спочатку прочитати **Туторіал - Посібник користувача** (те, що ви зараз читаєте).
|
||||
|
||||
Він розроблений таким чином, що ви можете створити повну програму лише за допомогою **Туторіал - Посібник користувача**, а потім розширити її різними способами, залежно від ваших потреб, використовуючи деякі з додаткових ідей з **Розширеного посібника користувача** .
|
||||
Він розроблений таким чином, що ви можете створити повну програму лише за допомогою **Туторіал - Посібник користувача**, а потім розширити її різними способами, залежно від ваших потреб, використовуючи деякі з додаткових ідей з **Розширеного посібника користувача**.
|
||||
|
||||
@@ -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] *}
|
||||
|
||||
@@ -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}.
|
||||
|
||||
|
||||
@@ -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`.
|
||||
|
||||
Ці функції створені таким чином (замість використання класів напряму), щоб Ваш редактор не відзначав їхні типи як помилки.
|
||||
Ці функції створені таким чином (замість використання класів напряму), щоб ваш редактор не відзначав їхні типи як помилки.
|
||||
|
||||
Таким чином, Ви можете користуватися своїм звичайним редактором і інструментами для програмування без додаткових налаштувань для ігнорування таких помилок.
|
||||
Таким чином, ви можете користуватися своїм звичайним редактором і інструментами для програмування без додаткових налаштувань для ігнорування таких помилок.
|
||||
|
||||
///
|
||||
|
||||
@@ -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** порівняно з альтернативними фреймворками (окрім сирої продуктивності).
|
||||
|
||||
@@ -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 та заголовків, але про це Ви дізнаєтеся пізніше в цьому посібнику. 🤫
|
||||
|
||||
|
||||
@@ -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`.
|
||||
|
||||
Дивіться наступні розділи, щоб дізнатися, як оголошувати валідації для інших типів, наприклад чисел.
|
||||
|
||||
@@ -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}.
|
||||
|
||||
///
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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-моделі для оголошення полів форми. 😎
|
||||
|
||||
@@ -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` разом, коли вам потрібно отримувати дані та файли в одному запиті.
|
||||
|
||||
@@ -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` для оголошення вхідних параметрів у вигляді даних форми.
|
||||
|
||||
@@ -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`, щоб повертати лише явно встановлені значення.
|
||||
|
||||
@@ -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}, ви побачите, як повертати інший код статусу, ніж значення за замовчуванням, яке ви оголошуєте тут.
|
||||
|
||||
@@ -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 або вище** — і все стане значно **простішим, узгодженим та інтуїтивно зрозумілим**, і Вам не доведеться знати всі ці історичні деталі. 😎
|
||||
|
||||
@@ -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.
|
||||
А також побачите, як це автоматично інтегрується в інтерактивну систему документації.
|
||||
|
||||
@@ -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>.
|
||||
|
||||
@@ -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` автоматично знайде файли з тестами, виконає їх і надасть вам результати.
|
||||
Він автоматично знайде файли та тести, виконає їх і повідомить вам результати.
|
||||
|
||||
Запустіть тести за допомогою:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user