Ну что ж, настало время изучить мощный инструмент валидации данных — Pydantic.
Зачем он нужен? Давайте разберемся.
Когда мы работаем с данными, будь то входящие запросы от пользователя или ответы от вашего API, важно быть уверенным в их корректности. Представьте, что ваш API получает JSON с "имя пользователя" как число вместо строки. Или, например, обработка "возраста" в виде строки "двадцать" вызовет крушение системы. Такие ошибки могут приводить к неожиданным багам, ломать код и создавать хаос.
Вот здесь на арену выходит Pydantic. Он заботится о валидации данных и их преобразовании. Pydantic позволяет:
- Автоматически проверять входящие данные.
- Гарантировать корректные типы данных.
- Создавать понятные сообщения об ошибках, если данные некорректны.
- Обрабатывать сложные структуры данных, такие как вложенные JSON.
Pydantic — это библиотека для работы с данными, которая используется в FastAPI для валидации запросов и ответов. Она как строгий, но заботливый учитель: проверяет каждую строчку данных, приводит их к правильным типам, а если что-то не так — говорит об этом простым языком.
Основные возможности Pydantic
- Простота создания моделей
Pydantic позволяет определять модели данных (или схемы) с использованием аннотаций типов Python. Да, тех самых
int,str,List,Dictи прочих.Это делается с помощью классов, которые наследуются от
pydantic.BaseModel.from pydantic import BaseModel class User(BaseModel): id: int name: str is_active: boolЧто здесь происходит?
- Мы создали модель
User. - Поля
id,name,is_activeпредставляют данные, которые мы ожидаем. - Аннотации типов (
int,str,bool) указывают, какого типа данные должны приходить.
Это как написать паспорт для данных: у каждого есть свое строгое место и строгое типовое соответствие.
- Мы создали модель
- Автоматическая валидация данных
Когда Pydantic сталкивается с вашими данными, он автоматически проверяет их соответствие заявленным типам и преобразует, если это возможно.
Пример проверки:
user_data = {"id": "123", "name": "Alice", "is_active": "true"} user = User(**user_data) print(user) # Пользователь преобразуется в: id=123, name='Alice', is_active=TruePydantic спокойно приводит строку
"123"к числу, а"true"к булевому значениюTrue.Но если поступят некорректные данные, например,
"id": "abc", будет вызвано исключение с подробным сообщением об ошибке. - Поддержка сложных структур данных
Вы можете определять вложенные модели для работы с более сложными данными.
from typing import List class Order(BaseModel): order_id: int product_name: str quantity: int class Customer(BaseModel): id: int name: str orders: List[Order]JSON, соответствующий этим моделям:
{ "id": 1, "name": "John", "orders": [ {"order_id": 101, "product_name": "Laptop", "quantity": 1}, {"order_id": 102, "product_name": "Mouse", "quantity": 2} ] } - Понятные сообщения об ошибках
Pydantic предоставляет подробные и понятные сообщения об ошибках. Давайте посмотрим пример:
invalid_user_data = {"id": "abc", "name": 123, "is_active": "yes"} user = User(**invalid_user_data)Вы увидите что-то вроде:
pydantic.error_wrappers.ValidationError: 2 validation errors for User id value is not a valid integer (type=type_error.integer) name str type expected (type=type_error.str)Сообщения достаточно информативны, чтобы быстро понять, где ошибка.
- Поддержка дефолтных значений
Pydantic поддерживает дефолтные значения для полей, что позволяет упростить обработку данных.
class Product(BaseModel): name: str price: float = 0.0 # По умолчанию цена товара — 0.0Если поле
priceотсутствует в запросе, Pydantic просто использует значение по умолчанию. - Документация из коробки
FastAPI автоматически интегрирует Pydantic-модели в OpenAPI-документацию.
Когда вы создаете Pydantic-модель и используете её в своих эндпоинтах, эта модель становится частью документации вашего API.
from fastapi import FastAPI app = FastAPI() class User(BaseModel): id: int name: str is_active: bool @app.post("/user/") async def create_user(user: User): return userСходите в ваш Swagger UI (
http://127.0.0.1:8000/docs), и вы увидите, как FastAPI автоматически добавил описание моделиUserв документацию. - Простота кастомизации
Хотите задать конкретное поведение для поля или сообщения об ошибке? Без проблем! Используйте
pydantic.Field.from pydantic import BaseModel, Field class Product(BaseModel): name: str = Field(max_length=50, description="Имя товара") price: float = Field(gt=0, description="Цена должна быть больше 0")Это не только валидирует данные (например, проверяет, что цена больше нуля), но и добавляет описание для документации.
Почему Pydantic важен в FastAPI
FastAPI интегрировал Pydantic глубоко в свою основу. Начиная от валидации запросов и заканчивая проверкой данных в ответах — вся магия происходит благодаря Pydantic. Использование Pydantic упрощает разработку, повышает надежность и уменьшает вероятность багов.
Представьте, что раньше вам приходилось явно проверять каждое значение типа "если это число", "если строка длиной не больше 10 символов". Теперь вы просто описываете модель, и Pydantic всё делает за вас.
Практическое задание
Теперь ваша очередь! Создайте Pydantic-модель для следующего JSON:
{
"username": "fastapi_user",
"age": 25,
"email": "user@example.com",
"is_premium": true
}
Добавьте валидацию:
- Поле age должно быть больше или равно 18.
- Поле email должно быть валидным адресом электронной почты.
- Поле is_premium — опционально, по умолчанию должно быть False.
Попробуйте интегрировать эту модель в эндпоинт FastAPI и протестируйте её с разными входными данными.
from typing import Optional
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr, Field
app = FastAPI()
class User(BaseModel):
username: str
age: int = Field(ge=18)
email: EmailStr
is_premium: bool | None = False
@app.post("/users/")
async def create_user(user: User):
return user
POST /users/
{
"username": "johndoe",
"age": 17,
"email": "notanemail"
}
Увидимся на следующей лекции, где мы углубимся в создание моделей с Pydantic и будем валидировать данные на практике! 🚀
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ