# Параметри шляху { #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** порівняно з альтернативними фреймворками (окрім сирої продуктивності).