from typing import Optional from sqlalchemy import ForeignKey, Text, Index from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.dialects.postgresql import TSVECTOR from db.base import Base class Category(Base): __tablename__ = "categories" id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) name: Mapped[str] = mapped_column(Text, nullable=False) parent_id: Mapped[Optional[int]] = mapped_column(ForeignKey("categories.id")) parent: Mapped["Category"] = relationship("Category", remote_side=[id]) class Product(Base): __tablename__ = "products" id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) category_id: Mapped[Optional[int]] = mapped_column(ForeignKey("categories.id")) name: Mapped[str] = mapped_column(Text, nullable=False) description: Mapped[Optional[str]] = mapped_column(Text) price: Mapped[int] = mapped_column() img_path: Mapped[str] = mapped_column(Text, nullable=False, unique=True) file_id: Mapped[str] = mapped_column(Text, nullable=True, unique=True) search_vector: Mapped[str] = mapped_column(TSVECTOR) __table_args__ = ( Index("idx_products_search", "search_vector", postgresql_using="gin"), )