10 KiB
Тіло - Вкладені моделі
З FastAPI ви можете визначати, перевіряти, документувати та використовувати моделі, які можуть бути вкладені на будь-яку глибину (завдяки Pydantic).
Поля списку
Ви можете визначити атрибут як підтип. Наприклад, Python-список (list):
{* ../../docs_src/body_nested_models/tutorial001_py310.py hl[12] *}
Це зробить tags списком, хоча не визначається тип елементів списку.
Поля списку з параметром типу
Але Python має специфічний спосіб оголошення списків з внутрішніми типами або «параметрами типу»:
Оголошення list з параметром типу
Щоб оголосити типи з параметрами типу (внутрішніми типами), такими як list, dict, tuple,
передайте внутрішні тип(и) як «параметри типу», використовуючи квадратні дужки: [ and ]
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 очікуватиме тіло запиту такого вигляду:
{
"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 тіло запиту у вигляді:
{
"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:
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, зберігаючи при цьому код простим, коротким та елегантним.
А також отримуєте всі переваги:
- Підтримка в редакторі (автодоповнення всюди!)
- Конвертація даних (парсинг/сериалізація)
- Валідацію даних
- Документація схем
- Автоматичне створення документації