Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Для чего нужен Pydantic
Pydantic — это мощная библиотека для валидации данных и парсинга конфигураций в Python. Она работает с типами данных, проверяет их корректность и преобразует данные из разных источников (JSON, словари, внешние API).
Основная задача Pydantic
Pydantic решает три основных проблемы:
- Валидация данных — проверка корректности
- Парсинг данных — преобразование из внешних форматов (JSON, БД)
- Типизация — явная типизация с runtime проверками
Проблема без Pydantic
# ❌ Без Pydantic — беспорядок
def create_user(data):
# Нужно вручную проверять каждое поле
if not isinstance(data.get('name'), str):
raise ValueError('Name must be string')
if not isinstance(data.get('age'), int):
raise ValueError('Age must be integer')
if data.get('age') < 0 or data.get('age') > 150:
raise ValueError('Age must be 0-150')
if '@' not in data.get('email', ''):
raise ValueError('Invalid email')
# Нет гарантии, что все поля присутствуют
user = User(
name=data['name'],
age=data['age'],
email=data.get('email', ''),
phone=data.get('phone') # Может быть None
)
return user
Решение с Pydantic
from pydantic import BaseModel, Field, EmailStr, validator
from typing import Optional
class User(BaseModel):
name: str # Обязательное поле, тип string
age: int # Обязательное, тип int
email: EmailStr # Автоматическая валидация email
phone: Optional[str] = None # Опциональное поле
# Пользовательская валидация
@validator('age')
def age_must_be_valid(cls, v):
if v < 0 or v > 150:
raise ValueError('Age must be 0-150')
return v
# ✅ Валидация автоматическая
user = User(name="Alice", age=30, email="alice@example.com")
print(user) # name='Alice' age=30 email='alice@example.com' phone=None
# ❌ Неправильные данные будут отклонены
try:
bad_user = User(name="Bob", age="invalid", email="not-an-email")
except ValueError as e:
print(e) # 1 validation error for User
Основные возможности Pydantic
1. Валидация типов
from pydantic import BaseModel
class Product(BaseModel):
name: str
price: float
quantity: int
# ✅ Правильные данные
product = Product(name="Laptop", price=999.99, quantity=5)
# ❌ Неправильный тип
try:
bad = Product(name="Phone", price="expensive", quantity=2) # price должно быть float
except Exception as e:
print(e) # Input should be a valid number
2. Значения по умолчанию и опциональные поля
from pydantic import BaseModel, Field
from datetime import datetime
from typing import Optional
class Blog(BaseModel):
title: str
content: str
author: str
views: int = 0 # Значение по умолчанию
created_at: datetime = Field(default_factory=datetime.now) # Функция для значения
tags: Optional[list[str]] = None # Опциональное
blog = Blog(
title="Python Tips",
content="Learn Python best practices",
author="Alice"
)
print(blog.views) # 0
print(blog.tags) # None
3. Сложные типы данных
from pydantic import BaseModel
from typing import List, Dict
from datetime import date
class Company(BaseModel):
name: str
employees: List[str] # Список строк
budget: Dict[str, float] # Словарь
founded: date # Дата автоматически парсится
company = Company(
name="TechCorp",
employees=["Alice", "Bob", "Charlie"],
budget={"R&D": 500000, "Marketing": 200000},
founded="2020-01-15" # Строка преобразуется в date
)
print(company.founded) # 2020-01-15
4. Вложенные модели
from pydantic import BaseModel, EmailStr
from typing import List
class Address(BaseModel):
street: str
city: str
zipcode: str
class Person(BaseModel):
name: str
email: EmailStr
address: Address # Вложенная модель
# Парсинг из словаря
person = Person(
name="Alice",
email="alice@example.com",
address={ # Автоматически преобразуется в Address
"street": "123 Main St",
"city": "New York",
"zipcode": "10001"
}
)
print(person.address.city) # New York
5. Валидаторы для кастомной логики
from pydantic import BaseModel, field_validator, ValidationInfo
class Registration(BaseModel):
username: str
password: str
password_confirm: str
age: int
@field_validator('username')
@classmethod
def username_valid(cls, v):
if len(v) < 3:
raise ValueError('Username must be at least 3 characters')
if not v.isalnum():
raise ValueError('Username must be alphanumeric')
return v
@field_validator('password')
@classmethod
def password_strong(cls, v):
if len(v) < 8:
raise ValueError('Password must be at least 8 characters')
return v
@field_validator('password_confirm')
@classmethod
def passwords_match(cls, v, info: ValidationInfo):
password = info.data.get('password')
if v != password:
raise ValueError('Passwords do not match')
return v
@field_validator('age')
@classmethod
def age_valid(cls, v):
if v < 18:
raise ValueError('Must be at least 18')
return v
# Тестирование
try:
reg = Registration(
username="al", # Слишком короткий
password="short", # Слишком слабый
password_confirm="short",
age=16 # Слишком молодой
)
except Exception as e:
print(e) # 4 validation errors
6. Парсинг JSON и dict
from pydantic import BaseModel
import json
class Config(BaseModel):
host: str
port: int
debug: bool
# Из словаря
config_dict = {"host": "localhost", "port": 5432, "debug": True}
config = Config(**config_dict)
# Из JSON
json_str = '{"host": "127.0.0.1", "port": 8000, "debug": false}'
config2 = Config.model_validate_json(json_str)
# В JSON
json_output = config2.model_dump_json()
print(json_output) # {"host":"127.0.0.1","port":8000,"debug":false}
7. Сериализация с контролем
from pydantic import BaseModel, Field, ConfigDict
from typing import Optional
class User(BaseModel):
model_config = ConfigDict(validate_default=True)
name: str
password: str = Field(exclude=True) # Не включать в сериализацию
email: str = Field(alias='user_email') # Альтернативное имя
age: Optional[int] = Field(default=None, gt=0) # Больше 0
user = User(name="Alice", password="secret", user_email="alice@example.com", age=25)
# Сериализация без пароля
print(user.model_dump()) # {'name': 'Alice', 'email': 'alice@example.com', 'age': 25}
# С указанием алиаса в JSON
print(user.model_dump(by_alias=True))
Применение в FastAPI
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
from typing import Optional
app = FastAPI()
class UserCreate(BaseModel):
name: str
email: EmailStr
age: int
class UserResponse(BaseModel):
id: int
name: str
email: str
@app.post("/users/", response_model=UserResponse)
async def create_user(user: UserCreate): # Автоматическая валидация
# user уже валидирован!
# email проверен
# age — число
return UserResponse(id=1, name=user.name, email=user.email)
# Пример запроса с плохими данными
# POST /users/
# {"name": "Bob", "email": "not-an-email", "age": "twenty"}
# Ответ: 422 Unprocessable Entity с описанием ошибок валидации
Pydantic vs dataclass
# Pydantic
from pydantic import BaseModel, EmailStr
class PydanticUser(BaseModel):
name: str
email: EmailStr # Валидация email
age: int
# dataclass
from dataclasses import dataclass
@dataclass
class DataclassUser:
name: str
email: str # Нет валидации!
age: int
# Pydantic валидирует автоматически
user1 = PydanticUser(name="Alice", email="alice@example.com", age=30) # OK
try:
bad_user = PydanticUser(name="Bob", email="invalid", age="old") # Ошибка
except Exception:
pass
# dataclass не валидирует
user2 = DataclassUser(name="Bob", email="invalid", age="old") # OK! Но неправильно
print(user2.age) # "old" — строка вместо числа
Best Practices с Pydantic
from pydantic import BaseModel, Field, field_validator, ConfigDict
from typing import Optional, List
from enum import Enum
class StatusEnum(str, Enum):
active = "active"
inactive = "inactive"
pending = "pending"
class Product(BaseModel):
model_config = ConfigDict(
validate_default=True,
str_strip_whitespace=True, # Убирать пробелы
use_enum_values=True # Использовать значения enum
)
id: int
name: str = Field(..., min_length=1, max_length=100)
price: float = Field(..., gt=0) # Больше 0
status: StatusEnum = StatusEnum.active
tags: List[str] = Field(default_factory=list)
description: Optional[str] = None
@field_validator('name')
@classmethod
def name_cannot_be_empty(cls, v):
if not v.strip():
raise ValueError('Name cannot be empty')
return v
# Использование
product = Product(
id=1,
name=" Laptop ", # Будет преобразовано в "Laptop"
price=999.99,
status="active",
tags=["electronics", "computers"]
)
Заключение
Pydantic — это必须 инструмент для:
- Валидации входных данных (API, формы, конфиги)
- Парсинга JSON и внешних данных
- Обеспечения типобезопасности
- Автоматической документации (OpenAPI)
- Работы с FastAPI и другими фреймворками
Она экономит часы на написание валидационного кода и делает ваше приложение более надежным и безопасным.