66 lines
2.1 KiB
Python
66 lines
2.1 KiB
Python
"""Playlist-Sound relationship model for managing sound order in playlists."""
|
|
|
|
from datetime import datetime
|
|
from typing import TYPE_CHECKING, Optional
|
|
from zoneinfo import ZoneInfo
|
|
|
|
from sqlalchemy import DateTime, ForeignKey, Integer, UniqueConstraint
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from app.database import db
|
|
|
|
if TYPE_CHECKING:
|
|
from app.models.playlist import Playlist
|
|
from app.models.sound import Sound
|
|
|
|
|
|
class PlaylistSound(db.Model):
|
|
"""Model for playlist-sound relationships with ordering."""
|
|
|
|
__tablename__ = "playlist_sound"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
|
playlist_id: Mapped[int] = mapped_column(
|
|
Integer, ForeignKey("playlist.id"), nullable=False
|
|
)
|
|
sound_id: Mapped[int] = mapped_column(
|
|
Integer, ForeignKey("sound.id"), nullable=False
|
|
)
|
|
order: Mapped[int] = mapped_column(Integer, nullable=False)
|
|
added_at: Mapped[datetime] = mapped_column(
|
|
DateTime,
|
|
default=lambda: datetime.now(tz=ZoneInfo("UTC")),
|
|
nullable=False,
|
|
)
|
|
|
|
# Relationships
|
|
playlist: Mapped["Playlist"] = relationship(
|
|
"Playlist", back_populates="playlist_sounds"
|
|
)
|
|
sound: Mapped["Sound"] = relationship(
|
|
"Sound", back_populates="playlist_sounds"
|
|
)
|
|
|
|
# Constraints
|
|
__table_args__ = (
|
|
UniqueConstraint(
|
|
"playlist_id", "sound_id", name="unique_playlist_sound"
|
|
),
|
|
UniqueConstraint("playlist_id", "order", name="unique_playlist_order"),
|
|
)
|
|
|
|
def __repr__(self) -> str:
|
|
"""String representation of the playlist-sound relationship."""
|
|
return f"<PlaylistSound(playlist_id={self.playlist_id}, sound_id={self.sound_id}, order={self.order})>"
|
|
|
|
def to_dict(self) -> dict:
|
|
"""Convert playlist-sound relationship to dictionary representation."""
|
|
return {
|
|
"id": self.id,
|
|
"playlist_id": self.playlist_id,
|
|
"sound_id": self.sound_id,
|
|
"order": self.order,
|
|
"added_at": self.added_at.isoformat() if self.added_at else None,
|
|
"sound": self.sound.to_dict() if self.sound else None,
|
|
}
|