У FastAPI на базі Pydantic Field дозволяє задавати додаткові налаштування для полів моделей. Це піднімає валідацію даних на новий рівень. За допомогою Field можна:
- Налаштовувати значення за замовчуванням для полів.
- Обмежувати можливі значення (наприклад, мінімальна довжина рядка, діапазон чисел).
- Додавати метадані (описи, приклади).
- Вказувати додаткові умови валідації.
Якщо подумати, то Field — це як чекліст правил для кожного поля. У кожного програміста є своя варіація «що перевірити перед здачею проєкту», так само й у нашого API є сувора перевірка даних через Field.
Проста аналогія: якби наші дані були гостем на вечірці, то Field — це строгий дядько-сек'юріті, який перевіряє, чи гість одягнений пристойно, чи є в нього запрошення і, звісно, чи не надто голосний у нього сміх.
Синтаксис Field
Щоб використати Field, просто імпортуємо його з pydantic і додаємо в опис моделі:
from pydantic import BaseModel, Field
class User(BaseModel):
username: str = Field(..., min_length=3, max_length=50, description="Ім'я користувача")
age: int = Field(..., ge=18, le=150, description="Вік користувача (повинен бути від 18 до 150)")
Розберемо параметри:
...(Ellipsis) означає, що поле обов'язкове.min_lengthіmax_lengthзадають мінімальну і максимальну довжину рядка.ge(greater or equal) іle(less or equal) задають діапазон значень для числа.descriptionдодає опис для документації.
Як використовувати Field в реальних проєктах?
Давайте створимо модель для реєстрації користувачів. Параметри повинні валідовуватися наступним чином:
- Ім'я користувача (
username) — має бути обов'язковим, довжина від 3 до 50 символів. - Електронна пошта (
email) — рядок, який має бути валідним email. - Вік (
age) — обов'язковий, від 18 до 120 років. - Опис (
bio) — необов'язкове поле, не довше 300 символів.
Приклад коду:
from pydantic import BaseModel, Field, EmailStr
class RegisterUser(BaseModel):
username: str = Field(..., min_length=3, max_length=50, description="Ім'я користувача")
email: EmailStr = Field(..., description="Електронна пошта користувача")
age: int = Field(..., ge=18, le=120, description="Вік користувача")
bio: str = Field(None, max_length=300, description="Короткий опис про користувача")
# Приклад використання:
input_data = {
"username": "JohnDoe",
"email": "john.doe@example.com",
"age": 25,
"bio": "I love Python and FastAPI!"
}
user = RegisterUser(**input_data)
print(user)
Що відбувається під час валідації?
Якщо дані відповідають вимогам, Pydantic створює об'єкт моделі на основі вхідних даних. Якщо якийсь параметр не проходить перевірку, буде викинуто виняток ValidationError з детальним описом, що пішло не так.
Наприклад, якщо передати в age від'ємне значення:
input_data = {
"username": "JohnDoe",
"email": "john.doe@example.com",
"age": -5, # Це явно не ок!
"bio": "I love Python and FastAPI!"
}
try:
user = RegisterUser(**input_data)
except ValidationError as e:
print(e.json())
Отримуємо:
[
{
"loc": ["age"],
"msg": "ensure this value is greater than or equal to 18",
"type": "value_error.number.not_ge",
"ctx": {"limit_value": 18}
}
]
Налаштування значень за замовчуванням
Якщо поле не обов'язкове, можна вказати значення за замовчуванням, яке автоматично підставиться за відсутності даних:
class User(BaseModel):
username: str = Field(..., min_length=3, max_length=50)
age: int = Field(30, ge=18, le=120) # Значення за замовчуванням — 30
bio: str = Field("No bio provided.", max_length=300) # Опис за замовчуванням
# Приклад:
input_data = {
"username": "JaneDoe"
}
user = User(**input_data)
print(user)
# Вивід: username='JaneDoe' age=30 bio='No bio provided.'
Опис полів для документації OpenAPI
FastAPI автоматично використовує описи, вказані в Field, щоб доповнити документацію. Якщо відкрити автоматично згенерований Swagger UI, можна побачити красиві описи всіх полів:
from fastapi import FastAPI
app = FastAPI()
@app.post("/users/")
async def create_user(user: RegisterUser):
return user
Тепер, зайшовши на /docs, ви побачите кожен наш опис, приклади і обмеження. Презентабельно і професійно!
Додаткові параметри
alias— задає альтернативну назву поля (наприклад, для сумісності з зовнішніми API).example— задає приклад значення (відображається в Swagger UI).regex— дозволяє вказати регулярний вираз для перевірки даних.
Приклад використання alias і regex:
Спробуємо створити модель, яка валідовує телефонні номери:
class PhoneNumber(BaseModel):
phone: str = Field(..., regex=r"^\+\d{1,3}-\d{3}-\d{4}$", alias="phone_number", example="+123-456-7890")
# Приклад:
input_data = {"phone_number": "+123-456-7890"}
phone = PhoneNumber(**input_data)
print(phone)
Модель перевірить, що номер телефону відповідає формату +XXX-XXX-XXXX. Якщо рядок не відповідає регулярному виразу, буде викинута помилка.
Типові помилки при роботі з Field
Інколи розробники стикаються з такими проблемами:
- Помилка з обов'язковими полями. Якщо забути вказати значення для обов'язкового поля (з
...), Pydantic кинеValidationError. - Неправильні типи даних. Якщо передати рядок замість числа або навпаки, відбудеться помилка валідації. Pydantic перевіряє типи даних досить строго.
- Ігнорування метаданих. Деякі новачки не вказують описи, приклади або зручні обмеження, що ускладнює підтримку коду в майбутньому.
Практичне завдання
Давайте напишемо модель для додавання товарів в інтернет-магазин. У товару має бути:
- Назва (
name), обов'язкова, до 100 символів. - Ціна (
price), обов'язкове поле, додатне число. - Категорія (
category), рядок, значення за замовчуванням — "general". - Опис (
description), необов'язкове поле, не більше 500 символів.
Реалізуйте ендпоінт /products/, який приймає цю модель і повертає збережені дані.
Рішення:
from fastapi import FastAPI
from pydantic import BaseModel, Field
app = FastAPI()
class Product(BaseModel):
name: str = Field(..., max_length=100, description="Назва товару")
price: float = Field(..., gt=0, description="Ціна товару (має бути додатною)")
category: str = Field("general", description="Категорія товару")
description: str = Field(None, max_length=500, description="Опис товару")
@app.post("/products/")
async def create_product(product: Product):
return {"msg": "Товар успішно додано!", "product": product}
Отже, тепер ти можеш налаштовувати поля у своїх моделях як профі. Твій код став не лише надійнішим, а й елегантнішим. Продовжуємо! 😉
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ