Сьогодні ми розширимо наші знання і навчимося створювати та обробляти вкладені структури даних. Адже в реальних застосунках запити рідко складаються з одного рівня ключ-значення. JSON-об'єкти з вкладенням — наше все! А якщо ти мріяв відчути себе програмістом, «який гуляє по лісу JSON-дерев», — твоя мрія здійснюється.
Уяви, що ти розробляєш API для інтернет-магазину. Запит від клієнта може містити масив товарів, кожен з яких має свої атрибути: назву, ціну, категорію і навіть вкладені об'єкти — наприклад, інформацію про постачальника. Ці дані потрібно валідовати не лише на верхньому рівні, а й глибше — для кожного товару і пов'язаних об'єктів. Pydantic дозволяє нам впоратися з цим елегантно і ефективно.
Що таке вкладені моделі?
У Pydantic вкладені моделі — це моделі, які містять інші Pydantic-моделі як атрибути. По суті, це спосіб побудувати деревоподібні структури даних, де кожен рівень даних валідовується автоматично.
Ось аналогія: уяви матрьошку. Кожен вкладений рівень перевіряється на відповідність певним правилам, які задають форму даних. В результаті у тебе цілісна і структурована модель.
Теорія: Як це працює?
Робота з вкладеними моделями базується на використанні моделей всередині інших моделей. Цього досягають шляхом вказання атрибута як екземпляра класу іншої моделі. Pydantic потім бере на себе обов'язки перевірити коректність даних на кожному рівні.
Ключові моменти:
- Зв'язування моделей: одна модель може бути атрибутом іншої.
- Рекурсивна перевірка: Pydantic автоматично валідовує вкладені моделі.
- Реалізація через анотації типів: використовуються анотації типів Python для вказання вкладених даних.
Приклад простої вкладеної моделі
Почнемо зі створення простої структури даних, де замовлення (Order) містить інформацію про користувача (User) і список товарів (Item).
from pydantic import BaseModel
from typing import List
class User(BaseModel):
id: int
name: str
email: str
class Item(BaseModel):
id: int
name: str
price: float
class Order(BaseModel):
user: User
items: List[Item]
Тут:
Userописує користувача.Itemописує товар.Orderмістить посилання на користувача і список товарів.
Тепер ми можемо використовувати Order для валідації даних, що містять вкладені структури.
Приклад використання
order_data = {
"user": {
"id": 1,
"name": "Іван Іванов",
"email": "ivan.ivanov@example.com"
},
"items": [
{"id": 101, "name": "Ноутбук", "price": 499.99},
{"id": 102, "name": "Миша", "price": 9.99}
]
}
order = Order(**order_data)
print(order)
Вивід буде приблизно таким:
user=User(id=1, name='Іван Іванов', email='ivan.ivanov@example.com')
items=[Item(id=101, name='Ноутбук', price=499.99), Item(id=102, name='Миша', price=9.99)]
Якщо в даних буде помилка, наприклад, у товару не вказано price, Pydantic викине виключення, що вказує, що поле price є обов'язковим.
Вкладені моделі та валідація
Давай подивимось, як Pydantic справляється з некоректними даними.
broken_order_data = {
"user": {
"id": 1,
"name": "Іван Іванов",
"email": "ivan.ivanov@example"
},
"items": [
{"id": 101, "name": "Ноутбук"},
{"id": 102, "name": "Миша", "price": "дев'ять"}
]
}
try:
broken_order = Order(**broken_order_data)
except Exception as e:
print(e)
Вивід:
1 validation error for Order
user -> email
value is not a valid email address (type=value_error.email)
items -> 0 -> price
field required (type=value_error.missing)
items -> 1 -> price
value is not a valid float (type=type_error.float)
Кожне проблемне поле позначене детальним повідомленням про помилку. Зручно, правда?
Робота зі складнішими структурами
Наприклад, замовлення може включати не лише користувача та товари, а й дані про доставку. Створимо модель з додатковим вкладенням.
class Address(BaseModel):
street: str
city: str
zip_code: str
class Shipping(BaseModel):
address: Address
delivery_date: str
class ExtendedOrder(BaseModel):
user: User
items: List[Item]
shipping: Shipping
Тепер дані виглядатимуть так:
extended_order_data = {
"user": {
"id": 1,
"name": "Іван Іванов",
"email": "ivan.ivanov@example.com"
},
"items": [
{"id": 101, "name": "Ноутбук", "price": 499.99},
{"id": 102, "name": "Миша", "price": 9.99}
],
"shipping": {
"address": {
"street": "Вулиця Леніна, буд.1",
"city": "Москва",
"zip_code": "101000"
},
"delivery_date": "2023-11-01"
}
}
order = ExtendedOrder(**extended_order_data)
print(order)
Помилки та типові проблеми
- Опечатки у вкладених даних: якщо поле вкладеної моделі опущено, це викличе помилку. Переконайся, що передав усі обов'язкові атрибути.
- Неправильні типи: якщо дані мають невірний тип (наприклад, рядок замість числа), Pydantic одразу видасть помилку.
- Занадто глибока вкладеність: оптимально уникати складних і заплутаних вкладених структур, бо це ускладнює обробку.
Підсумкові зауваження
Вкладені моделі — це життєво важливий інструмент для реалізації складних систем. Вони допомагають нам валідовувати структуру навіть найвитонченіших JSON-ів, зменшуючи ймовірність обробки некоректних даних. Забезпечивши роботу з FastAPI і Pydantic, твоя робота з даними стане не лише потужнішою, але й простішою.
У наступній лекції ми продовжимо занурюватися в тонкощі валідації і навчимося працювати з обов'язковими та опціональними полями!
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ