diff --git a/HWs/Sergey/homework2/homework02.py b/HWs/Sergey/homework2/homework02.py new file mode 100644 index 0000000..b183442 --- /dev/null +++ b/HWs/Sergey/homework2/homework02.py @@ -0,0 +1,131 @@ +'''Разработать систему регистрации пользователя, используя Pydantic для валидации входных данных, обработки +вложенных структур и сериализации. Система должна обрабатывать данные в формате JSON. + +Задачи: +1. Создать классы моделей данных с помощью Pydantic для пользователя и его адреса. +2. Реализовать функцию, которая принимает JSON строку, десериализует её в объекты Pydantic, валидирует данные, и в +случае успеха сериализует объект обратно в JSON и возвращает его. +3. Добавить кастомный валидатор для проверки соответствия возраста и статуса занятости пользователя. +4. Написать несколько примеров JSON строк для проверки различных сценариев валидации: успешные регистрации и случаи, +когда валидация не проходит (например возраст не соответствует статусу занятости). + +Модели: +Address: Должен содержать следующие поля: +city: строка, минимум 2 символа. +street: строка, минимум 3 символа. +house_number: число, должно быть положительным. + +User: Должен содержать следующие поля: +name: строка, должна быть только из букв, минимум 2 символа. +age: число, должно быть между 0 и 120. +email: строка, должна соответствовать формату email. +is_employed: булево значение, статус занятости пользователя. +address: вложенная модель адреса. + +Валидация: +Проверка, что если пользователь указывает, что он занят (is_employed = true), его возраст должен быть от 18 до 65 +лет. + +# Пример JSON данных для регистрации пользователя +json_input = """{ + "name": "John Doe", + "age": 70, + "email": "john.doe@example.com", + "is_employed": true, + "address": { + "city": "New York", + "street": "5th Avenue", + "house_number": 123 + } + }""" +''' + +from pydantic import BaseModel, ValidationError, Field, EmailStr, model_validator + + +class Address(BaseModel): + city: str = Field(min_length=2, description='Min length 2 characters') + street: str = Field(min_length=3, description='Min length 3 characters') + house_number: int = Field(gt=0, description='Always positive integer') + + +class User(BaseModel): + name: str = Field(pattern=r'^[a-zA-Zа-яА-Я -]+$', min_length=2, description='Only letters and min 2 characters') + age: int = Field(gt=0, le=120, description='Between 0 and 120') + email: EmailStr = Field(description='Email address format') + is_employed: bool + address: Address + + + @model_validator(mode='after') + def check_is_employed(self): + if self.is_employed and not (18 <= self.age <= 65): + raise ValueError("If user is employed, age must be between 18 and 65") + return self + + +def data_validator(data): + try: + user = User.model_validate_json(data, strict=True) + return user.model_dump_json() + except ValidationError as err: + return err.json() + # except ValueError as err: + # print("ValueError error:", err) + + +if __name__ == '__main__': + # valid + # json_input = """{ + # "name": "John Doe", + # "age": 70, + # "email": "john.doe@example.com", + # "is_employed": true, + # "address": { + # "city": "New York", + # "street": "5th Avenue", + # "house_number": 123 + # } + # }""" + + json_input = """{ + "name": "Michael Johnson", + "age": 52, + "email": "mjohnson@gmail.com", + "is_employed": false, + "address": { + "city": "New York", + "street": "7th Avenue", + "house_number": 25 + } + }""" + print('User registration is successful') + print(data_validator(json_input)) + + # invalid email and house_number + # json_input = """{ + # "name": "Barak Obama", + # "age": 61, + # "email": "@icloud.co", + # "is_employed": false, + # "address": { + # "city": "Washington", + # "street": "1", + # "house_number": "12a" + # } + # }""" + + # invalid age + json_invalid = """{ + "name": "Timbuktu", + "age": 70, + "email": "tb@icloud.com", + "is_employed": true, + "address": { + "city": "Boston", + "street": "Baker Street", + "house_number": 124 + } + }""" + print('User registration is not successful') + print(data_validator(json_invalid)) diff --git a/HWs/Sergey/homework4/homework04.py b/HWs/Sergey/homework4/homework04.py new file mode 100644 index 0000000..70e7683 --- /dev/null +++ b/HWs/Sergey/homework4/homework04.py @@ -0,0 +1,96 @@ +'''Задача 1: Наполнение данными +Добавьте в базу данных следующие категории и продукты''' +from sqlalchemy import create_engine, Column, Integer, String, DECIMAL, Boolean, Text, ForeignKey, func +from sqlalchemy.orm import sessionmaker, declarative_base, relationship + + +engine = create_engine('sqlite:///:memory:') + +Base = declarative_base() + +Session = sessionmaker(bind=engine) +session = Session() + + +class Product(Base): + __tablename__ = 'product' + id = Column(Integer, primary_key=True, autoincrement=True) + name = Column(String(100)) + price = Column(DECIMAL(7,2)) + in_stock = Column(Boolean) + category_id = Column(Integer, ForeignKey('category.id')) + + +class Category(Base): + __tablename__ = 'category' + id = Column(Integer, primary_key=True, autoincrement=True) + name = Column(String(100)) + description = Column(Text) + products = relationship("Product", backref="category") + + +Base.metadata.create_all(engine) + +'''Добавление категорий: Добавьте в таблицу categories следующие категории: +Название: "Электроника", Описание: "Гаджеты и устройства." +Название: "Книги", Описание: "Печатные книги и электронные книги." +Название: "Одежда", Описание: "Одежда для мужчин и женщин."''' +category_1 = Category(name="Электроника", description="Гаджеты и устройства.") +category_2 = Category(name="Книги", description="Печатные книги и электронные книги.") +category_3 = Category(name="Одежда", description="Одежда для мужчин и женщин.") + +session.add_all([category_1, category_2, category_3]) +session.commit() + +'''Добавление продуктов: Добавьте в таблицу products следующие продукты, убедившись, что каждый продукт связан с +соответствующей категорией: +Название: "Смартфон", Цена: 299.99, Наличие на складе: True, Категория: Электроника +Название: "Ноутбук", Цена: 499.99, Наличие на складе: True, Категория: Электроника +Название: "Научно-фантастический роман", Цена: 15.99, Наличие на складе: True, Категория: Книги +Название: "Джинсы", Цена: 40.50, Наличие на складе: True, Категория: Одежда +Название: "Футболка", Цена: 20.00, Наличие на складе: True, Категория: Одежда''' +product_1 = Product(name="Смартфон", price=299.99, in_stock=True, category_id=1) +product_2 = Product(name="Ноутбук", price=499.99, in_stock=True, category_id=1) +product_3 = Product(name="Научно-фантастический роман", price=15.99, in_stock=True, category_id=2) +product_4 = Product(name="Джинсы", price=40.50, in_stock=True, category_id=3) +product_5 = Product(name="Футболка", price=20.00, in_stock=True, category_id=3) + +session.add_all([product_1, product_2, product_3, product_4, product_5]) +session.commit() + +'''Задача 2: Чтение данных +Извлеките все записи из таблицы categories. Для каждой категории извлеките и выведите все связанные с ней продукты, +включая их названия и цены.''' +query_category = session.query(Category).all() +for category in query_category: + print(f"{category.id}. {category.name} - {category.description}:") + for product in category.products: + print(f" *** Название: {product.name}, Цена: {product.price}, Наличие: {product.in_stock}") + print("-" * 70) + +'''Задача 3: Обновление данных +Найдите в таблице products первый продукт с названием "Смартфон". Замените цену этого продукта на 349.99.''' +product = session.query(Product).filter(Product.name == "Смартфон").first() +product.price = 349.99 +session.commit() +print("-" * 70) +print(f" *** Название: {product.name}, Цена: {product.price}, Наличие: {product.in_stock}") + +'''Задача 4: Агрегация и группировка +Используя агрегирующие функции и группировку, подсчитайте общее количество продуктов в каждой категории.''' +total_prod_in_ctg = (session.query(Category.name, func.count(Product.id).label('count_products')).outerjoin(Product + ).group_by(Category.id).order_by(Category.id).all()) +print("-" * 70) +for item in total_prod_in_ctg: + print("-" * 70) + print(f"Категория: '{item[0]}' - Количество: {item[1]}") +print("-" * 70) + +'''Задача 5: Группировка с фильтрацией +Отфильтруйте и выведите только те категории, в которых более одного продукта.''' +print("-" * 70) +ctg_with_mult_prod = (session.query(Category.name, func.count(Product.id).label('count_products')).outerjoin(Product + ).group_by(Category.id).having(func.count(Product.id) > 1).all()) +print("Категории с более чем 1 продуктом:") +for item in ctg_with_mult_prod: + print(item[0])