diff --git a/docs/uk/docs/tutorial/body-nested-models.md b/docs/uk/docs/tutorial/body-nested-models.md new file mode 100644 index 000000000..abc33f2eb --- /dev/null +++ b/docs/uk/docs/tutorial/body-nested-models.md @@ -0,0 +1,245 @@ +# Тіло запиту - Вкладені моделі + +З **FastAPI** Ви можете визначати, перевіряти, документувати та використовувати моделі, які можуть бути вкладені на будь-яку глибину (завдяки Pydantic). + +## Поля списку + +Ви можете визначити атрибут як підтип. Наприклад, Python-список (`list`): + +{* ../../docs_src/body_nested_models/tutorial001_py310.py hl[12] *} + +Це зробить `tags` списком, хоча не визначається тип елементів списку. + +## Поля списку з параметром типу + +Але Python має специфічний спосіб оголошення списків з внутрішніми типами або "параметрами типу": +### Імпортуємо `List` з модуля typing + +У Python 3.9 і вище можна використовувати стандартний `list` для оголошення таких типів, як ми побачимо нижче. 💡 + +Але в 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 це буде виглядати так: + +```Python +my_list: list[str] +``` + +У версіях Python до 3.9 це виглядає так: + +```Python +from typing import List + +my_list: List[str] +``` + +Це стандартний синтаксис Python для оголошення типів. + +Використовуйте той самий стандартний синтаксис для атрибутів моделей з внутрішніми типами. + +Отже, у нашому прикладі, ми можемо зробити `tags` саме "списком рядків": + +{* ../../docs_src/body_nested_models/tutorial002_py310.py hl[12] *} + +## Типи множин + +Але потім ми подумали, що теги не повинні повторюватися, вони, ймовірно, повинні бути унікальними рядками. + +І Python має спеціальний тип даних для множин унікальних елементів — це `set`. + +Тому ми можемо оголосити `tags` як множину рядків: + +{* ../../docs_src/body_nested_models/tutorial003_py310.py hl[12] *} + +Навіть якщо Ви отримаєте запит з дубльованими даними, він буде перетворений у множину унікальних елементів. + +І коли Ви будете виводити ці дані, навіть якщо джерело містить дублікати, вони будуть виведені як множина унікальних елементів. + +І це буде анотовано/документовано відповідно. + +## Вкладені моделі + +Кожен атрибут моделі Pydantic має тип. + +Але цей тип сам може бути іншою моделлю Pydantic. + +Отже, Ви можете оголосити глибоко вкладені JSON "об'єкти" з конкретними іменами атрибутів, типами та перевірками. + +Усе це, вкладене без обмежень. + +### Визначення підмоделі + +Наприклад, ми можемо визначити модель `Image`: + +{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[7:9] *} + +### Використання підмоделі як типу + +А потім ми можемо використовувати її як тип атрибута: + +{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[18] *} + +Це означатиме, що **FastAPI** очікуватиме тіло запиту такого вигляду: + +```JSON +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2, + "tags": ["rock", "metal", "bar"], + "image": { + "url": "http://example.com/baz.jpg", + "name": "The Foo live" + } +} +``` + +Завдяки такій декларації у **FastAPI** Ви отримуєте: + +* Підтримку в редакторі (автозавершення тощо), навіть для вкладених моделей +* Конвертацію даних +* Валідацію даних +* Автоматичну документацію + +## Спеціальні типи та валідація + +Окрім звичайних типів, таких як `str`, `int`, `float`, та ін. Ви можете використовувати складніші типи, які наслідують `str`. + +Щоб побачити всі доступні варіанти, ознайомтеся з оглядом типів у Pydantic. Деякі приклади будуть у наступних розділах. + +Наприклад, у моделі `Image` є поле `url`, тому ми можемо оголосити його як `HttpUrl` від Pydantic замість `str`: + +{* ../../docs_src/body_nested_models/tutorial005_py310.py hl[2,8] *} + +Рядок буде перевірено як дійсну URL-адресу і задокументовано в JSON Schema / OpenAPI як URL. + +## Атрибути зі списками підмоделей + +У Pydantic Ви можете використовувати моделі як підтипи для `list`, `set` тощо: + +{* ../../docs_src/body_nested_models/tutorial006_py310.py hl[18] *} + +Це означає, що **FastAPI** буде очікувати (конвертувати, валідувати, документувати тощо) JSON тіло запиту у вигляді: + +```JSON hl_lines="11" +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2, + "tags": [ + "rock", + "metal", + "bar" + ], + "images": [ + { + "url": "http://example.com/baz.jpg", + "name": "The Foo live" + }, + { + "url": "http://example.com/dave.jpg", + "name": "The Baz" + } + ] +} +``` + +/// info | Інформація + +Зверніть увагу, що тепер ключ `images` містить список об'єктів зображень. + +/// + +## Глибоко вкладені моделі + +Ви можете визначати вкладені моделі довільної глибини: + +{* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *} + +/// info | Інформація + +Зверніть увагу, що в моделі `Offer` є список `Item`ів, які, своєю чергою, можуть мати необов'язковий список `Image`ів. + +/// + +## Тіла запитів, що складаються зі списків + +Якщо верхній рівень JSON тіла, яке Ви очікуєте, є JSON `масивом` (у Python — `list`), Ви можете оголосити тип у параметрі функції, як і в моделях Pydantic: + +```Python +images: List[Image] +``` +або в Python 3.9 і вище: + +```Python +images: list[Image] +``` + +наприклад: + +{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *} + +## Підтримка в редакторі всюди + +Ви отримаєте підтримку в редакторі всюди. + +Навіть для елементів у списках: + + + +Ви не змогли б отримати таку підтримку в редакторі, якби працювали напряму зі `dict`, а не з моделями Pydantic. + +Але Вам не потрібно турбуватися про це: вхідні dict'и автоматично конвертуються, а вихідні дані автоматично перетворюються в JSON. + +## Тіла з довільними `dict` + +Ви також можете оголосити тіло як `dict` з ключами одного типу та значеннями іншого типу. + +Це корисно, якщо Ви не знаєте наперед, які імена полів будуть дійсними (як у випадку з моделями Pydantic). + +Це буде корисно, якщо Ви хочете приймати ключі, які заздалегідь невідомі. + +--- + +Це також зручно, якщо Ви хочете мати ключі іншого типу (наприклад, `int`). + +Ось що ми розглянемо далі. + +У цьому випадку Ви можете приймати будь-який `dict`, якщо його ключі — це `int`, а значення — `float`: + +{* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *} + +/// tip | Порада + +Майте на увазі, що в JSON тілі ключі можуть бути лише рядками (`str`). + +Але Pydantic автоматично конвертує дані. + +Це означає, що навіть якщо клієнти вашого API надсилатимуть ключі у вигляді рядків, якщо вони містять цілі числа, Pydantic конвертує їх і проведе валідацію. + +Тобто `dict`, який Ви отримаєте як `weights`, матиме ключі типу `int` та значення типу `float`. + +/// + +## Підсумок + +З **FastAPI** Ви маєте максимальну гнучкість завдяки моделям Pydantic, зберігаючи при цьому код простим, коротким та елегантним. + +А також отримуєте всі переваги: + +* Підтримка в редакторі (автодоповнення всюди!) +* Конвертація даних (парсинг/сериалізація) +* Валідація даних +* Документація схем +* Автоматичне створення документації