Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Продвинутая сериализация: сериализаторы и контекст
serialization_advanced

Продвинутая сериализация: сериализаторы и контекст

Кастомные сериализаторы через @field_serializer, режим wrap, передача контекста при сериализации.

Продвинутая сериализация: сериализаторы и контекст

Кастомные сериализаторы позволяют полностью контролировать вывод данных

#@field_serializer: кастомизация поля

@field_serializer позволяет изменить формат вывода конкретного поля:

from pydantic import BaseModel, field_serializer from datetime import datetime class User(BaseModel): name: str created_at: datetime @field_serializer('created_at') def serialize_created_at(self, value: datetime) -> str: return value.strftime('%Y-%m-%d %H:%M') user = User(name="Alice", created_at=datetime(2026, 3, 18, 10, 30)) print(user.model_dump()) # {'name': 'Alice', 'created_at': '2026-03-18 10:30'}

#Режимы сериализации: return_type и mode

from pydantic import BaseModel, field_serializer from datetime import datetime class Event(BaseModel): name: str start: datetime end: datetime @field_serializer('start', return_type=str) def serialize_start(self, value: datetime) -> str: return value.isoformat() @field_serializer('end', mode='wrap') def serialize_end(self, value: datetime, handler): # handler — стандартный сериализатор serialized = handler(value) return f"Ends at: {serialized}" event = Event( name="Conference", start=datetime(2026, 3, 18, 9, 0), end=datetime(2026, 3, 18, 18, 0) ) print(event.model_dump()) # {'name': 'Conference', 'start': '2026-03-18T09:00:00', # 'end': 'Ends at: 2026-03-18T18:00:00'}

#mode='wrap': полный контроль

from pydantic import BaseModel, field_serializer from decimal import Decimal class Product(BaseModel): name: str price: Decimal @field_serializer('price', mode='wrap') def serialize_price(self, value: Decimal, handler) -> str: # Стандартная сериализация serialized = handler(value) # Форматирование как валюта return f"${float(value):.2f}" product = Product(name="Widget", price=Decimal("19.99")) print(product.model_dump()) # {'name': 'Widget', 'price': '$19.99'}

#Сериализация нескольких полей

from pydantic import BaseModel, field_serializer from datetime import datetime class Event(BaseModel): name: str created_at: datetime updated_at: datetime @field_serializer('created_at', 'updated_at') def serialize_dates(self, value: datetime) -> str: return value.strftime('%Y-%m-%d') event = Event( name="Meeting", created_at=datetime(2026, 3, 18, 10, 0), updated_at=datetime(2026, 3, 18, 11, 0) ) print(event.model_dump()) # {'name': 'Meeting', 'created_at': '2026-03-18', 'updated_at': '2026-03-18'}

#@model_serializer: кастомизация всей модели

@model_serializer позволяет переопределить сериализацию всей модели:

from pydantic import BaseModel, model_serializer from datetime import datetime class User(BaseModel): name: str email: str password_hash: str created_at: datetime @model_serializer def serialize_user(self) -> dict: return { 'name': self.name, 'email': self.email, 'created_at': self.created_at.strftime('%Y-%m-%d') # password_hash не включается } user = User( name="Alice", email="alice@example.com", password_hash="hashed_value", created_at=datetime.now() ) print(user.model_dump()) # {'name': 'Alice', 'email': 'alice@example.com', 'created_at': '2026-03-18'}

#mode='wrap' для model_serializer

from pydantic import BaseModel, model_serializer class User(BaseModel): name: str email: str role: str = "user" @model_serializer(mode='wrap') def serialize_user(self, handler): # Стандартная сериализация data = handler(self) # Добавление метаданных data['_serialized_at'] = datetime.now().isoformat() data['_version'] = '1.0' return data user = User(name="Alice", email="alice@example.com") print(user.model_dump()) # {'name': 'Alice', 'email': 'alice@example.com', 'role': 'user', # '_serialized_at': '2026-03-18T10:30:00', '_version': '1.0'}

#Контекст при сериализации

from pydantic import BaseModel, field_serializer, SerializationInfo from datetime import datetime class User(BaseModel): name: str email: str is_admin: bool last_login: datetime | None = None @field_serializer('last_login') def serialize_last_login( self, value: datetime | None, info: SerializationInfo ) -> str | None: # Доступ к контексту context = info.context if context and context.get('show_last_login'): return value.isoformat() if value else None # Скрываем last_login по умолчанию return None user = User( name="Alice", email="alice@example.com", is_admin=True, last_login=datetime(2026, 3, 18, 10, 0) ) # Без контекста print(user.model_dump()) # {'name': 'Alice', 'email': 'alice@example.com', 'is_admin': True} # С контекстом print(user.model_dump(context={'show_last_login': True})) # {'name': 'Alice', 'email': 'alice@example.com', 'is_admin': True, # 'last_login': '2026-03-18T10:00:00'}

#Условная сериализация

from pydantic import BaseModel, field_serializer, field_validator from typing import Any class SecureModel(BaseModel): data: dict[str, Any] sensitivity: str # 'public', 'internal', 'confidential' @field_serializer('data') def serialize_data(self, value: dict) -> dict: if self.sensitivity == 'confidential': # Маскирование чувствительных данных return {k: '***' for k in value} elif self.sensitivity == 'internal': # Удаление некоторых полей return {k: v for k, v in value.items() if not k.startswith('_')} return value public = SecureModel(data={'key': 'value'}, sensitivity='public') internal = SecureModel(data={'key': 'value', '_secret': 'hidden'}, sensitivity='internal') confidential = SecureModel(data={'key': 'value'}, sensitivity='confidential') print(public.model_dump()) # {'data': {'key': 'value'}, 'sensitivity': 'public'} print(internal.model_dump()) # {'data': {'key': 'value'}, 'sensitivity': 'internal'} print(confidential.model_dump()) # {'data': {'key': '***'}, 'sensitivity': 'confidential'}

#Сериализация вложенных моделей

from pydantic import BaseModel, field_serializer from datetime import datetime class Address(BaseModel): street: str city: str zip_code: str class User(BaseModel): name: str address: Address updated_at: datetime @field_serializer('address') def serialize_address(self, value: Address) -> str: return f"{value.street}, {value.city}" @field_serializer('updated_at') def serialize_updated_at(self, value: datetime) -> str: return value.strftime('%Y-%m-%d') user = User( name="Alice", address=Address(street="123 Main St", city="NYC", zip_code="10001"), updated_at=datetime.now() ) print(user.model_dump()) # {'name': 'Alice', 'address': '123 Main St, NYC', 'updated_at': '2026-03-18'}

#Сериализация коллекций

from pydantic import BaseModel, field_serializer from datetime import datetime class Event(BaseModel): name: str date: datetime class Calendar(BaseModel): name: str events: list[Event] @field_serializer('events') def serialize_events(self, value: list[Event]) -> list[dict]: return [ {'name': e.name, 'date': e.date.strftime('%Y-%m-%d')} for e in value ] calendar = Calendar( name="Work", events=[ Event(name="Meeting", date=datetime(2026, 3, 18, 10, 0)), Event(name="Deadline", date=datetime(2026, 3, 20, 18, 0)) ] ) print(calendar.model_dump()) # {'name': 'Work', 'events': [ # {'name': 'Meeting', 'date': '2026-03-18'}, # {'name': 'Deadline', 'date': '2026-03-20'} # ]}

#Мини-проект: API Response с кастомной сериализацией

Создайте систему ответов API с кастомной сериализацией:

from pydantic import BaseModel, field_serializer, model_serializer, Field from datetime import datetime from typing import Any, Optional, Generic, TypeVar T = TypeVar('T') class APIResponse(BaseModel, Generic[T]): """Универсальный ответ API с кастомной сериализацией""" success: bool data: T message: Optional[str] = None timestamp: datetime = Field(default_factory=datetime.now) request_id: str # Добавьте @field_serializer для: # - timestamp: формат ISO 8601 # - data: кастомная сериализация в зависимости от типа # Добавьте @model_serializer(mode='wrap') для: # - Добавления версии API в ответ # - Условного включения message (только если не None) class UserData(BaseModel): id: int username: str email: str password_hash: str # не должен сериализоваться created_at: datetime # Добавьте @field_serializer для: # - created_at: формат 'YYYY-MM-DD' # - password_hash: возвращать '***' вместо значения # Пример использования: # response = APIResponse[UserData]( # success=True, # data=UserData(id=1, username="alice", email="alice@example.com", # password_hash="hashed", created_at=datetime.now()), # request_id="req-123" # ) # print(response.model_dump())

Далее: Обработка ошибок: ValidationError и кастомизация