801e6a050b
- Documentation archivée et réorganisée - Backend: Ajout tests, migrations, library service, rate limiting - Frontend: Suppression Flutter, focus sur interface web HTML/JS - Tailwind CSS ajouté pour le style - Améliorations UX et corrections bugs Generated with [Claude Code](https://claude.com/claude-code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
91 lines
2.4 KiB
Python
91 lines
2.4 KiB
Python
"""Liked Track model."""
|
|
import uuid
|
|
from datetime import datetime
|
|
from typing import TYPE_CHECKING
|
|
|
|
from sqlalchemy import String, ForeignKey, Index
|
|
from sqlalchemy.dialects.postgresql import UUID
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from app.core.database import Base
|
|
|
|
if TYPE_CHECKING:
|
|
from app.models.user import User
|
|
from app.models.track import Track
|
|
|
|
|
|
class LikedTrack(Base):
|
|
"""Liked Track model representing user's liked/favorited tracks."""
|
|
|
|
__tablename__ = "liked_tracks"
|
|
|
|
# Primary key
|
|
id: Mapped[uuid.UUID] = mapped_column(
|
|
UUID(as_uuid=True),
|
|
primary_key=True,
|
|
default=uuid.uuid4,
|
|
index=True,
|
|
)
|
|
|
|
# Foreign keys
|
|
user_id: Mapped[uuid.UUID] = mapped_column(
|
|
UUID(as_uuid=True),
|
|
ForeignKey("users.id", ondelete="CASCADE"),
|
|
nullable=False,
|
|
index=True,
|
|
)
|
|
track_id: Mapped[uuid.UUID] = mapped_column(
|
|
UUID(as_uuid=True),
|
|
ForeignKey("tracks.id", ondelete="CASCADE"),
|
|
nullable=False,
|
|
index=True,
|
|
)
|
|
|
|
# Additional metadata
|
|
notes: Mapped[str | None] = mapped_column(
|
|
String(1000),
|
|
nullable=True,
|
|
comment="User notes about the track",
|
|
)
|
|
|
|
# Timestamps
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
default=datetime.utcnow,
|
|
nullable=False,
|
|
)
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
default=datetime.utcnow,
|
|
onupdate=datetime.utcnow,
|
|
nullable=False,
|
|
)
|
|
|
|
# Relationships
|
|
user: Mapped["User"] = relationship(
|
|
"User",
|
|
back_populates="liked_tracks",
|
|
lazy="selectin",
|
|
)
|
|
track: Mapped["Track"] = relationship(
|
|
"Track",
|
|
lazy="selectin",
|
|
)
|
|
|
|
# Table indices for optimal queries and uniqueness constraint
|
|
__table_args__ = (
|
|
Index("ix_liked_tracks_user_track", "user_id", "track_id", unique=True),
|
|
)
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<LikedTrack user={self.user_id} track={self.track_id}>"
|
|
|
|
def to_dict(self) -> dict:
|
|
"""Convert liked track model to dictionary."""
|
|
return {
|
|
"id": str(self.id),
|
|
"user_id": str(self.user_id),
|
|
"track_id": str(self.track_id),
|
|
"notes": self.notes,
|
|
"created_at": self.created_at.isoformat(),
|
|
"updated_at": self.updated_at.isoformat(),
|
|
}
|