# Параметри шляху { #path-parameters }
Ви можете оголосити «параметри» або «змінні» шляху, використовуючи той самий синтаксис, що й у форматованих рядках Python:
{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *}
Значення параметра шляху `item_id` буде передано у вашу функцію як аргумент `item_id`.
Отже, якщо ви запустите цей приклад і перейдете за посиланням http://127.0.0.1:8000/items/foo, то побачите відповідь:
```JSON
{"item_id":"foo"}
```
## Параметри шляху з типами { #path-parameters-with-types }
Ви можете оголосити тип параметра шляху у функції, використовуючи стандартні анотації типів Python:
{* ../../docs_src/path_params/tutorial002_py39.py hl[7] *}
У цьому випадку `item_id` оголошено як `int`.
/// check | Примітка
Це дасть вам підтримку редактора всередині функції з перевірками помилок, автодоповненням тощо.
///
## Перетворення даних { #data-conversion }
Якщо ви запустите цей приклад і відкриєте у браузері http://127.0.0.1:8000/items/3, то побачите відповідь:
```JSON
{"item_id":3}
```
/// check | Примітка
Зверніть увагу, що значення, яке отримала (і повернула) ваша функція, — це `3`, як Python `int`, а не рядок `"3"`.
Отже, з таким оголошенням типу **FastAPI** надає вам автоматичний «parsing» запиту.
///
## Валідація даних { #data-validation }
Але якщо ви перейдете у браузері за посиланням http://127.0.0.1:8000/items/foo, ви побачите гарну 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"
}
]
}
```
тому що параметр шляху `item_id` мав значення `"foo"`, яке не є `int`.
Та сама помилка з’явиться, якщо ви передасте `float` замість `int`, як у: http://127.0.0.1:8000/items/4.2
/// check | Примітка
Отже, з тим самим оголошенням типу в Python **FastAPI** надає вам валідацію даних.
Зверніть увагу, що помилка також чітко вказує саме місце, де валідація не пройшла.
Це неймовірно корисно під час розробки та налагодження коду, що взаємодіє з вашим API.
///
## Документація { #documentation }
А коли ви відкриєте у браузері http://127.0.0.1:8000/docs, ви побачите автоматичну, інтерактивну, API-документацію на кшталт:
/// check | Примітка
Знову ж таки, лише з тим самим оголошенням типу в Python **FastAPI** надає вам автоматичну, інтерактивну документацію (з інтеграцією Swagger UI).
Зверніть увагу, що параметр шляху оголошено як ціле число.
///
## Переваги стандартів, альтернативна документація { #standards-based-benefits-alternative-documentation }
І оскільки згенерована схема відповідає стандарту OpenAPI, існує багато сумісних інструментів.
Через це **FastAPI** також надає альтернативну API-документацію (використовуючи ReDoc), до якої ви можете отримати доступ за посиланням http://127.0.0.1:8000/redoc:
Так само, існує багато сумісних інструментів. Зокрема інструменти генерації коду для багатьох мов.
## Pydantic { #pydantic }
Уся валідація даних виконується за лаштунками за допомогою Pydantic, тож ви отримуєте всі переваги від його використання. І ви знаєте, що ви в надійних руках.
Ви можете використовувати ті самі оголошення типів з `str`, `float`, `bool` та багатьма іншими складними типами даних.
Декілька з них розглядаються в наступних розділах посібника.
## Порядок має значення { #order-matters }
Під час створення *операцій шляху* можуть виникати ситуації, коли у вас є фіксований шлях.
Наприклад, `/users/me` — припустімо, це для отримання даних про поточного користувача.
І тоді у вас також може бути шлях `/users/{user_id}` для отримання даних про конкретного користувача за його ID.
Оскільки *операції шляху* оцінюються по черзі, вам потрібно переконатися, що шлях для `/users/me` оголошено перед шляхом для `/users/{user_id}`:
{* ../../docs_src/path_params/tutorial003_py39.py hl[6,11] *}
Інакше шлях для `/users/{user_id}` також відповідатиме `/users/me`, «вважаючи», що отримує параметр `user_id` зі значенням `"me"`.
Так само ви не можете перевизначити операцію шляху:
{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *}
Завжди використовуватиметься перша, оскільки шлях збігається першим.
## Попередньо визначені значення { #predefined-values }
Якщо у вас є *операція шляху*, яка отримує *параметр шляху*, але ви хочете, щоб можливі коректні значення *параметра шляху* були попередньо визначені, ви можете використати стандартний Python `Enum`.
### Створіть клас `Enum` { #create-an-enum-class }
Імпортуйте `Enum` і створіть підклас, що наслідується від `str` та `Enum`.
Завдяки наслідуванню від `str` документація API зможе визначити, що значення повинні бути типу `string`, і зможе коректно їх відобразити.
Після цього створіть атрибути класу з фіксованими значеннями, які будуть доступними коректними значеннями:
{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *}
/// tip | Порада
Якщо вам цікаво, «AlexNet», «ResNet» та «LeNet» — це просто назви Machine Learning models.
///
### Оголосіть *параметр шляху* { #declare-a-path-parameter }
Потім створіть *параметр шляху* з анотацією типу, використовуючи створений вами клас enum (`ModelName`):
{* ../../docs_src/path_params/tutorial005_py39.py hl[16] *}
### Перевірте документацію { #check-the-docs }
Оскільки доступні значення для *параметра шляху* визначені заздалегідь, інтерактивна документація може красиво їх показати:
### Робота з Python *переліченнями* { #working-with-python-enumerations }
Значення *параметра шляху* буде *елементом перелічування*.
#### Порівняйте *елементи перелічування* { #compare-enumeration-members }
Ви можете порівнювати його з *елементом перелічування* у створеному вами enum `ModelName`:
{* ../../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_py39.py hl[20] *}
/// tip | Порада
Ви також можете отримати доступ до значення `"lenet"` через `ModelName.lenet.value`.
///
#### Поверніть *елементи перелічування* { #return-enumeration-members }
Ви можете повертати *елементи enum* з вашої *операції шляху*, навіть вкладені у JSON-тіло (наприклад, `dict`).
Вони будуть перетворені на відповідні значення (у цьому випадку рядки) перед поверненням клієнту:
{* ../../docs_src/path_params/tutorial005_py39.py hl[18,21,23] *}
На стороні клієнта ви отримаєте відповідь у форматі JSON, наприклад:
```JSON
{
"model_name": "alexnet",
"message": "Deep Learning FTW!"
}
```
## Параметри шляху, що містять шляхи { #path-parameters-containing-paths }
Припустімо, у вас є *операція шляху* зі шляхом `/files/{file_path}`.
Але вам потрібно, щоб `file_path` сам містив *шлях*, наприклад `home/johndoe/myfile.txt`.
Отже, URL для цього файлу виглядатиме приблизно так: `/files/home/johndoe/myfile.txt`.
### Підтримка OpenAPI { #openapi-support }
OpenAPI не підтримує спосіб оголошення *параметра шляху*, який має містити всередині *шлях*, оскільки це може призвести до сценаріїв, які складно тестувати та визначати.
Проте ви все одно можете зробити це в **FastAPI**, використовуючи один із внутрішніх інструментів Starlette.
І документація все ще працюватиме, хоча й не додаватиме жодної документації, яка б казала, що параметр має містити шлях.
### Конвертер шляху { #path-convertor }
Використовуючи опцію безпосередньо зі Starlette, ви можете оголосити *параметр шляху*, що містить *шлях*, використовуючи URL на кшталт:
```
/files/{file_path:path}
```
У цьому випадку ім’я параметра — `file_path`, а остання частина `:path` вказує, що параметр має відповідати будь-якому *шляху*.
Отже, ви можете використати його так:
{* ../../docs_src/path_params/tutorial004_py39.py hl[6] *}
/// tip | Порада
Вам може знадобитися, щоб параметр містив `/home/johndoe/myfile.txt` із початковою косою рискою (`/`).
У такому випадку URL виглядатиме так: `/files//home/johndoe/myfile.txt`, із подвійною косою рискою (`//`) між `files` і `home`.
///
## Підсумок { #recap }
З **FastAPI**, використовуючи короткі, інтуїтивно зрозумілі та стандартні оголошення типів Python, ви отримуєте:
* Підтримку редактора: перевірка помилок, автодоповнення тощо.
* Перетворення даних «parsing»
* Валідацію даних
* Анотацію API та автоматичну документацію
І вам потрібно оголосити їх лише один раз.
Це, ймовірно, основна видима перевага **FastAPI** порівняно з альтернативними фреймворками (окрім сирої продуктивності).