Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added HWs/DmitriyK/HM4/hm4.db
Binary file not shown.
110 changes: 110 additions & 0 deletions HWs/DmitriyK/HM4/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import logging

from sqlalchemy import (
DECIMAL,
Boolean,
Column,
Float,
ForeignKey,
Integer,
Numeric,
String,
Table,
create_engine,
func,
)
from sqlalchemy.orm import DeclarativeBase, declarative_base, relationship, sessionmaker

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("sqlalchemy.engine")
logger.setLevel(logging.INFO)

Base = declarative_base()
engine = create_engine("sqlite:///hm4.db")


class Category(Base):
__tablename__ = "categories"
id = Column(Integer, primary_key=True)
name = Column(String(50))
description = Column(String(100))
in_stock = Column(Boolean, default=True)
products = relationship("Product", back_populates="category")


class Product(Base):
__tablename__ = "products"
id = Column(Integer, primary_key=True)
name = Column(String(100), nullable=False)
price = Column(Numeric(precision=10, scale=2))
in_stock = Column(Boolean, default=True)
category_id = Column(Integer, ForeignKey("categories.id"))
category = relationship("Category", back_populates="products")


Base.metadata.drop_all(engine)
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)

with Session() as session:
with session.begin():
electronics = Category(name="Electronics", description="Gadgets and devices.")
books = Category(name="Books", description="Printed and electronic books.")
clothing = Category(name="Clothing", description="Clothing for men and women.")
session.add_all([electronics, books, clothing])
session.commit()

products = [
Product(name="Smartphone", price=299.99, category=electronics),
Product(name="Laptop", price=499.99, category=electronics),
Product(name="Sci-Fi Novel", price=15.99, category=books),
Product(name="Jeans", price=40.50, category=clothing),
Product(name="T-shirt", price=20.00, category=clothing),
]
session.add_all(products)
session.commit()

with Session() as session:
all_categories = session.query(Category).all()

for category in all_categories:
Comment on lines +68 to +70

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

У вас выходит проблема N+1. Потому что вы извлекаете связанные объекты множеством запросов в цикле. Лучше сделать 1 большой запрос

Suggested change
all_categories = session.query(Category).all()
for category in all_categories:
data = session.query(Category, Product).join(Product).all()
for category, product in data:
# дальше сами

Либо тоже через join, но уже по конкретным полям и таблица с Product будет слева

Suggested change
all_categories = session.query(Category).all()
for category in all_categories:
data = session.query(Category.name, Product.name, Product.price).join(Category).all()
for category, product, price in data:

print(f"\nCategory: {category.name}")
print(f"Description: {category.description}")
if category.products:
for product in category.products:
print(f"Product: {product.name:<25} | Price: {product.price:>8.2f}")
else:
print(" (No products found in this category)")


with Session() as session:
target_product = session.query(Product).filter(Product.name == "Smartphone").first()
if target_product:
target_product.price = 349.99
session.commit()
print(f"Successfully updated price for: {target_product.name}")
else:
print("Product 'Smartphone' not found.")


with Session() as session:
results = (
session.query(Product.category_id, func.count(Product.id))
.group_by(Product.category_id)
.all()
)
for cat_id, count in results:
print(f"Category ID: {cat_id} | Total Products: {count}")


with Session() as session:
results = (
session.query(Product.category_id, func.count(Product.id))
.group_by(Product.category_id)
.having(func.count(Product.id) > 1)
.all()
)

print("\n--- Task 5: Categories with > 1 product ---")
for cat_id, count in results:
print(f"Category ID: {cat_id} | Total Products: {count}")