Текст задания
Объедини несколько задач практикума в один связный файл models.py. Цель — убедиться, что ты умеешь:
- Создать Pydantic v2 модели с кастомным валидатором и Field-ограничениями.
- Построить SQLAlchemy 2.x схему с двумя связанными таблицами.
- Провести полный цикл работы с сессией: add → commit → query → delete → commit.
Подзадача 1: Pydantic-модели
- Модель
Event(title, date, location)— полеdateдолжно быть в будущем (@field_validator). - Модель
UserProfile(username, password, email)— пароль не короче 8 символов, email черезEmailStr, пример вjson_schema_extra.
Подзадача 2: SQLAlchemy-модели
- Класс
Base(DeclarativeBase). - Модель
User(id, name, age)с relationship наAddress. - Модель
Address(id, street, user_id)с ForeignKey наusers.id. - Engine:
sqlite:///:memory:сecho=True.
Подзадача 3: Сессия
- Создать нового пользователя и адрес, добавить в БД, сделать commit.
- Найти пользователя запросом, вывести имя и адрес.
- Удалить пользователя, сделать commit, проверить что вернулся
None.
Подготовка окружения
1. Создать виртуальное окружение
# PowerShell / cmd
python -m venv venv
venv\Scripts\activate # Windows
# source venv/bin/activate # macOS/Linux
2. Установить зависимости
pip install "pydantic[email]" sqlalchemy
3. Инициализировать Git-репозиторий
git init
git add models.py
git commit -m "feat: lesson 06 practice — Pydantic v2 + SQLAlchemy 2.x models"
# или создать ветку:
git checkout -b lesson/06-sqlalchemy-practice
Пошаговое решение
Шаг 1: импорты
Собираем все нужные импорты в начале файла:
# models.py
from pydantic import BaseModel, EmailStr, Field, ConfigDict, field_validator
from typing import Annotated, List, Optional
from decimal import Decimal
from datetime import datetime, timedelta
from sqlalchemy import create_engine, String, Integer, ForeignKey
from sqlalchemy.orm import (
DeclarativeBase, Mapped, mapped_column,
relationship, Session
)
Шаг 2: Pydantic-модели
Для Event используем @field_validator с @classmethod. Для UserProfile — Field(min_length=8), EmailStr и ConfigDict:
class Event(BaseModel):
title: str
date: datetime
location: str
@field_validator('date')
@classmethod
def date_must_be_future(cls, v: datetime) -> datetime:
if v < datetime.now():
raise ValueError("Event date must be in the future")
return v
class UserProfile(BaseModel):
username: str
password: str = Field(
min_length=8,
description="Password must be at least 8 characters long"
)
email: EmailStr
model_config = ConfigDict(
json_schema_extra={
"example": {
"username": "john_doe",
"password": "securePassword123",
"email": "john.doe@example.com"
}
}
)
Шаг 3: SQLAlchemy-схема
Базовый класс через наследование (SQLAlchemy 2.x). Поля через Mapped[тип] = mapped_column(...). Связь через relationship с back_populates на обеих сторонах:
engine = create_engine('sqlite:///:memory:', echo=True)
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = 'users'
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(50))
age: Mapped[int] = mapped_column(Integer)
addresses: Mapped[List["Address"]] = relationship(
"Address", back_populates="user"
)
class Address(Base):
__tablename__ = 'addresses'
id: Mapped[int] = mapped_column(primary_key=True)
street: Mapped[Optional[str]] = mapped_column(String(255))
user_id: Mapped[int] = mapped_column(ForeignKey('users.id'))
user: Mapped["User"] = relationship("User", back_populates="addresses")
# Создать таблицы в БД
Base.metadata.create_all(engine)
Шаг 4: работа с сессией
Используем контекстный менеджер with Session(engine) as session: — закрытие автоматическое. После commit() транзакция зафиксирована:
with Session(engine) as session:
# Создание
new_user = User(name="John Doe", age=28)
new_addr = Address(street="123 Elm Street", user=new_user)
session.add(new_user)
session.add(new_addr)
session.commit()
print(f"Created user id={new_user.id}, address={new_addr.street}")
with Session(engine) as session:
# Запрос
user = session.query(User).filter_by(name="John Doe").first()
print(f"Found: {user.name}, age={user.age}")
# Удаление
session.delete(user)
session.commit()
# Проверка
result = session.query(User).filter_by(name="John Doe").first()
print(f"After delete: {result}") # None
Шаг 5: тестирование Pydantic-моделей
if __name__ == "__main__":
# Тест Event
try:
evt = Event(
title="Conference",
date=datetime.now() + timedelta(days=7),
location="Moscow"
)
print(f"Event: {evt.title}, {evt.date}")
except Exception as e:
print(f"Event error: {e}")
# Тест UserProfile
try:
user = UserProfile(
username="alice",
password="strongPass1",
email="alice@example.com"
)
print(f"UserProfile: {user.username}, {user.email}")
except Exception as e:
print(f"UserProfile error: {e}")
Проверка в VS Code
Открыть проект и запустить файл
- Открыть папку в VS Code: File → Open Folder
- Убедиться, что выбран нужный Python-интерпретатор (из venv): Ctrl+Shift+P → Python: Select Interpreter
- Открыть терминал: Ctrl+`, активировать venv:
venv\Scripts\activate - Запустить файл в терминале:
python models.py - Или запустить через кнопку ▶️ в правом верхнем углу редактора.
Запуск через F5 с launch.json
Создайте файл .vscode/launch.json для запуска текущего файла:
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"justMyCode": true
}
]
}
После создания файла нажмите F5 для запуска с отладчиком.
Точки останова (breakpoints)
- Кликните слева от номера строки — появится красная точка (breakpoint).
- Нажмите F5 — выполнение остановится на этой строке.
- В панели Variables (слева) видны значения всех переменных.
- Используйте F10 (Step Over) и F11 (Step Into) для пошагового выполнения.
- В Debug Console (снизу) можно вводить Python-выражения в контексте текущей точки останова.
Рекомендуемые расширения VS Code
- Python (ms-python.python) — основное расширение
- Pylance (ms-python.vscode-pylance) — статический анализ, автодополнение с типами
- SQLTools — просмотр и редактирование баз данных прямо в VS Code
Связь с теорией
- Теория урока 06 — краткое повторение Pydantic v2 и SQLAlchemy 2.x
- Примеры урока 06 — рабочие примеры Event, UserProfile, Transaction, User+Address
- Урок 03: Библиотека Pydantic — полная теория по BaseModel, валидаторам, Field
- Урок 05: SQLAlchemy модели и поля — полная теория по ORM, движку, сессии