JavaRush /Курси /Модуль 4: FastAPI /Використання Field для налаштування полів моделей

Використання Field для налаштування полів моделей

Модуль 4: FastAPI
Рівень 3 , Лекція 3
Відкрита

У 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 в реальних проєктах?

Давайте створимо модель для реєстрації користувачів. Параметри повинні валідовуватися наступним чином:

  1. Ім'я користувача (username) — має бути обов'язковим, довжина від 3 до 50 символів.
  2. Електронна пошта (email) — рядок, який має бути валідним email.
  3. Вік (age) — обов'язковий, від 18 до 120 років.
  4. Опис (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, ви побачите кожен наш опис, приклади і обмеження. Презентабельно і професійно!


Додаткові параметри

  1. alias — задає альтернативну назву поля (наприклад, для сумісності з зовнішніми API).
  2. example — задає приклад значення (відображається в Swagger UI).
  3. 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

Інколи розробники стикаються з такими проблемами:

  1. Помилка з обов'язковими полями. Якщо забути вказати значення для обов'язкового поля (з ...), Pydantic кине ValidationError.
  2. Неправильні типи даних. Якщо передати рядок замість числа або навпаки, відбудеться помилка валідації. Pydantic перевіряє типи даних досить строго.
  3. Ігнорування метаданих. Деякі новачки не вказують описи, приклади або зручні обмеження, що ускладнює підтримку коду в майбутньому.

Практичне завдання

Давайте напишемо модель для додавання товарів в інтернет-магазин. У товару має бути:

  • Назва (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}

Отже, тепер ти можеш налаштовувати поля у своїх моделях як профі. Твій код став не лише надійнішим, а й елегантнішим. Продовжуємо! 😉

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ