Browse Source
Co-authored-by: Valentyn Druzhynin <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Sofie Van Landeghem <[email protected]>pull/13432/head
committed by
GitHub
1 changed files with 261 additions and 0 deletions
@ -0,0 +1,261 @@ |
|||||
|
# Path Параметри |
||||
|
|
||||
|
Ви можете визначити "параметри" або "змінні" шляху, використовуючи синтаксис форматованих рядків: |
||||
|
|
||||
|
{* ../../docs_src/path_params/tutorial001.py hl[6:7] *} |
||||
|
|
||||
|
Значення параметра шляху `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>, то отримаємо таку відповідь: |
||||
|
|
||||
|
```JSON |
||||
|
{"item_id":"foo"} |
||||
|
``` |
||||
|
|
||||
|
## Path параметри з типами |
||||
|
|
||||
|
Ви можете визначити тип параметра шляху у функції, використовуючи стандартні анотації типів Python: |
||||
|
|
||||
|
{* ../../docs_src/path_params/tutorial002.py hl[7] *} |
||||
|
|
||||
|
У такому випадку `item_id` визначається як `int`. |
||||
|
|
||||
|
/// check | Примітка |
||||
|
|
||||
|
Це дасть можливість підтримки редактора всередині функції з перевірками помилок, автодоповнення тощо. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## <abbr title="або: серіалізація, парсинг, маршалізація">Перетворення</abbr> даних |
||||
|
|
||||
|
Якщо запустити цей приклад і перейти за посиланням <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} |
||||
|
``` |
||||
|
|
||||
|
/// check | Примітка |
||||
|
|
||||
|
Зверніть увагу, що значення, яке отримала (і повернула) ваша функція, — це `3`. Це Python `int`, а не рядок `"3"`. |
||||
|
|
||||
|
Отже, з таким оголошенням типу **FastAPI** автоматично виконує <abbr title="перетворення рядка, що надходить із HTTP-запиту, у типи даних Python">"парсинг"</abbr> запитів. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## <abbr title="Або валідація">Перевірка</abbr> даних |
||||
|
|
||||
|
Якщо ж відкрити у браузері посилання <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 |
||||
|
{ |
||||
|
"detail": [ |
||||
|
{ |
||||
|
"type": "int_parsing", |
||||
|
"loc": [ |
||||
|
"path", |
||||
|
"item_id" |
||||
|
], |
||||
|
"msg": "Input should be a valid integer, unable to parse string as an integer", |
||||
|
"input": "foo", |
||||
|
"url": "https://errors.pydantic.dev/2.1/v/int_parsing" |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
``` |
||||
|
тому що параметр шляху має значення `"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. |
||||
|
|
||||
|
Зверніть увагу, що помилка також чітко вказує саме на те місце, де валідація не пройшла. |
||||
|
|
||||
|
Це неймовірно корисно під час розробки та дебагінгу коду, що взаємодіє з вашим 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). |
||||
|
|
||||
|
Зверніть увагу, що параметр шляху оголошений як ціле число. |
||||
|
|
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## Переваги стандартизації, альтернативна документація |
||||
|
|
||||
|
І оскільки згенерована схема відповідає стандарту <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>: |
||||
|
|
||||
|
<img src="/img/tutorial/path-params/image02.png"> |
||||
|
|
||||
|
Таким чином, існує багато сумісних інструментів, включаючи інструменти для генерації коду для багатьох мов. |
||||
|
|
||||
|
|
||||
|
## Pydantic |
||||
|
|
||||
|
Вся валідація даних виконується за лаштунками за допомогою <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a>, тому Ви отримуєте всі переваги від його використання. І можете бути впевнені, що все в надійних руках. |
||||
|
|
||||
|
Ви можете використовувати ті самі оголошення типів з `str`, `float`, `bool` та багатьма іншими складними типами даних. |
||||
|
|
||||
|
Декілька з них будуть розглянуті в наступних розділах посібника. |
||||
|
|
||||
|
## Порядок має значення |
||||
|
|
||||
|
При створенні *операцій шляху* можуть виникати ситуації, коли шлях фіксований. |
||||
|
|
||||
|
Наприклад, `/users/me`. Припустимо, що це шлях для отримання даних про поточного користувача. |
||||
|
|
||||
|
А також у вас може бути шлях `/users/{user_id}`, щоб отримати дані про конкретного користувача за його ID. |
||||
|
|
||||
|
Оскільки *операції шляху* оцінюються по черзі, Ви повинні переконатися, що шлях для `/users/me` оголошений перед шляхом для `/users/{user_id}`: |
||||
|
|
||||
|
{* ../../docs_src/path_params/tutorial003.py hl[6,11] *} |
||||
|
|
||||
|
Інакше шлях для `/users/{user_id}` також буде відповідати для `/users/me`, "вважаючи", що він отримує параметр `user_id` зі значенням `"me"`. |
||||
|
|
||||
|
Аналогічно, Ви не можете оголосити операцію шляху: |
||||
|
|
||||
|
{* ../../docs_src/path_params/tutorial003b.py hl[6,11] *} |
||||
|
|
||||
|
Перша операція буде завжди використовуватися, оскільки шлях збігається першим. |
||||
|
## Попередньо визначені значення |
||||
|
|
||||
|
Якщо у вас є *операція шляху*, яка приймає *параметр шляху*, але Ви хочете, щоб можливі допустимі значення *параметра шляху* були попередньо визначені, Ви можете використати стандартний Python <abbr title="перелічення">Enum</abbr>. |
||||
|
|
||||
|
### Створення класу `Enum` |
||||
|
|
||||
|
Імпортуйте `Enum` і створіть підклас, що наслідується від `str` та `Enum`. |
||||
|
|
||||
|
Наслідуючи від `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. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
/// tip | Порада |
||||
|
|
||||
|
Якщо вам цікаво, "AlexNet", "ResNet" та "LeNet" — це просто назви ML моделей <abbr title="Технічно, архітектури Deep Learning моделей">Machine Learning</abbr>. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
|
||||
|
### Оголосіть *параметр шляху* |
||||
|
|
||||
|
Потім створіть *параметр шляху* з анотацією типу, використовуючи створений вами клас enum (`ModelName`): |
||||
|
|
||||
|
{* ../../docs_src/path_params/tutorial005.py hl[16] *} |
||||
|
|
||||
|
### Перевірка документації |
||||
|
|
||||
|
Оскільки доступні значення для *параметра шляху* визначені заздалегідь, інтерактивна документація зможе красиво їх відобразити: |
||||
|
|
||||
|
<img src="/img/tutorial/path-params/image03.png"> |
||||
|
|
||||
|
### Робота з *перелічуваннями* у Python |
||||
|
|
||||
|
Значення *параметра шляху* буде елементом *перелічування*. |
||||
|
|
||||
|
#### Порівняння *елементів перелічування* |
||||
|
|
||||
|
Ви можете порівнювати його з *елементами перелічування* у створеному вами enum `ModelName`: |
||||
|
|
||||
|
{* ../../docs_src/path_params/tutorial005.py hl[17] *} |
||||
|
|
||||
|
#### Отримання *значення перелічування* |
||||
|
|
||||
|
Ви можете отримати фактичне значення (у цьому випадку це `str`), використовуючи `model_name.value`, або загалом `your_enum_member.value`: |
||||
|
|
||||
|
{* ../../docs_src/path_params/tutorial005.py hl[20] *} |
||||
|
|
||||
|
/// tip | Порада |
||||
|
|
||||
|
Ви також можете отримати доступ до значення `"lenet"`, використовуючи `ModelName.lenet.value`. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
|
||||
|
#### Повернення *елементів перелічування* |
||||
|
|
||||
|
Ви можете повертати *елементи перелічування* з вашої *операції шляху*, навіть вкладені у JSON-тіло (наприклад, `dict`). |
||||
|
|
||||
|
Вони будуть перетворені на відповідні значення (у цьому випадку рядки) перед поверненням клієнту: |
||||
|
|
||||
|
{* ../../docs_src/path_params/tutorial005.py hl[18,21,23] *} |
||||
|
|
||||
|
На стороні клієнта Ви отримаєте відповідь у форматі JSON, наприклад: |
||||
|
|
||||
|
```JSON |
||||
|
{ |
||||
|
"model_name": "alexnet", |
||||
|
"message": "Deep Learning FTW!" |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
## Path-параметри, що містять шляхи |
||||
|
|
||||
|
Припустимо, у вас є *операція шляху* з маршрутом `/files/{file_path}`. |
||||
|
|
||||
|
Але вам потрібно, щоб `file_path` містив *шлях*, наприклад `home/johndoe/myfile.txt`. |
||||
|
|
||||
|
Отже, URL для цього файлу виглядатиме так: `/files/home/johndoe/myfile.txt`. |
||||
|
|
||||
|
|
||||
|
|
||||
|
### Підтримка OpenAPI |
||||
|
|
||||
|
OpenAPI не підтримує спосіб оголошення *параметра шляху*, що містить *шлях* всередині, оскільки це може призвести до сценаріїв, які складно тестувати та визначати. |
||||
|
|
||||
|
Однак (одначе), Ви все одно можете зробити це в **FastAPI**, використовуючи один із внутрішніх інструментів Starlette. |
||||
|
|
||||
|
Документація все ще працюватиме, хоча й не додаватиме опису про те, що параметр повинен містити шлях. |
||||
|
|
||||
|
### Конвертер шляху |
||||
|
|
||||
|
Використовуючи опцію безпосередньо зі Starlette, Ви можете оголосити *параметр шляху*, що містить *шлях*, використовуючи URL на кшталт: |
||||
|
|
||||
|
``` |
||||
|
/files/{file_path:path} |
||||
|
``` |
||||
|
У цьому випадку ім'я параметра — `file_path`, а остання частина `:path` вказує на те, що параметр повинен відповідати будь-якому *шляху*. |
||||
|
|
||||
|
Отже, Ви можете використати його так: |
||||
|
|
||||
|
{* ../../docs_src/path_params/tutorial004.py hl[6] *} |
||||
|
|
||||
|
/// tip | Порада |
||||
|
|
||||
|
Вам може знадобитися, щоб параметр містив `/home/johndoe/myfile.txt` із початковою косою рискою (`/`). |
||||
|
|
||||
|
У такому випадку URL виглядатиме так: `/files//home/johndoe/myfile.txt`, із подвійною косою рискою (`//`) між `files` і `home`. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## Підсумок |
||||
|
|
||||
|
З **FastAPI**, використовуючи короткі, інтуїтивно зрозумілі та стандартні оголошення типів Python, Ви отримуєте: |
||||
|
|
||||
|
* Підтримку в редакторі: перевірка помилок, автодоповнення тощо. |
||||
|
* "<abbr title="перетворення рядка, що надходить з HTTP-запиту, у типи даних Python">Парсинг</abbr>" даних |
||||
|
* Валідацію даних |
||||
|
* Анотацію API та автоматичну документацію |
||||
|
|
||||
|
І вам потрібно оголосити їх лише один раз. |
||||
|
|
||||
|
Це, ймовірно, основна видима перевага **FastAPI** порівняно з альтернативними фреймворками (окрім високої продуктивності). |
Loading…
Reference in new issue