119 lines
3.3 KiB
Python
119 lines
3.3 KiB
Python
import os
|
|
import uuid
|
|
from io import BytesIO
|
|
|
|
from PIL import Image
|
|
from django.db import models
|
|
from core.models import BaseModel
|
|
|
|
|
|
def album_cover_upload_to(instance, filename):
|
|
ext = filename.split(".")[-1]
|
|
return os.path.join("album_covers", f"{uuid.uuid4()}.{ext}")
|
|
|
|
|
|
def artist_cover_upload_to(instance, filename):
|
|
ext = filename.split(".")[-1]
|
|
return os.path.join("artist_covers", f"{uuid.uuid4()}.{ext}")
|
|
|
|
|
|
def track_upload_to(instance, filename):
|
|
return os.path.join(
|
|
"music",
|
|
f"album_{instance.album_id}",
|
|
filename,
|
|
)
|
|
|
|
|
|
class Artist(BaseModel):
|
|
name = models.CharField(max_length=200)
|
|
cover_image = models.ImageField(
|
|
upload_to=artist_cover_upload_to, null=True, blank=True
|
|
)
|
|
|
|
def __str__(self):
|
|
return f"{self.name}"
|
|
|
|
|
|
class Album(BaseModel):
|
|
artist = models.ForeignKey(Artist, on_delete=models.CASCADE, related_name="albums")
|
|
name = models.CharField(max_length=200)
|
|
release_date = models.PositiveSmallIntegerField(default=0)
|
|
cover_image = models.ImageField(
|
|
upload_to=album_cover_upload_to, null=True, blank=True
|
|
)
|
|
preview_image = models.ImageField(null=True, blank=True)
|
|
|
|
def __str__(self):
|
|
return f"{self.artist} - {self.name}"
|
|
|
|
def create_preview_image(self):
|
|
# Placeholder for preview image creation logic
|
|
img = Image.open(self.cover_image)
|
|
|
|
target_height = 256
|
|
target_width = int((target_height / img.height) * img.width)
|
|
img = img.resize((target_width, target_height), Image.LANCZOS)
|
|
|
|
buffer = BytesIO()
|
|
img.save(buffer, format="JPEG")
|
|
buffer.seek(0)
|
|
|
|
self.preview_image.save(
|
|
os.path.join("album_previews", f"{uuid.uuid4()}.jpg"),
|
|
buffer,
|
|
save=False,
|
|
)
|
|
buffer.close()
|
|
|
|
def save(self, *args, **kwargs):
|
|
if not self.preview_image and self.cover_image:
|
|
self.create_preview_image()
|
|
super().save(*args, **kwargs)
|
|
|
|
|
|
class Track(BaseModel):
|
|
title = models.CharField(max_length=200)
|
|
album = models.ForeignKey(Album, on_delete=models.CASCADE, related_name="tracks")
|
|
file = models.FileField(upload_to=track_upload_to)
|
|
|
|
def __str__(self):
|
|
return f"{self.album.artist} - {self.title}"
|
|
|
|
|
|
class Playlist(BaseModel):
|
|
name = models.CharField(max_length=200)
|
|
tracks = models.ManyToManyField(Track, related_name="playlists")
|
|
|
|
def __str__(self):
|
|
return f"Playlist: {self.name}"
|
|
|
|
|
|
class RecommendationPlaylist(BaseModel):
|
|
class Meta:
|
|
constraints = [
|
|
models.UniqueConstraint(
|
|
fields=["is_actual"],
|
|
condition=models.Q(is_actual=True),
|
|
name="unique_actual_recommendation_playlist",
|
|
)
|
|
]
|
|
|
|
name = models.CharField(max_length=200)
|
|
description = models.TextField(blank=True)
|
|
playlist = models.OneToOneField(
|
|
Playlist, on_delete=models.CASCADE, related_name="recommendations"
|
|
)
|
|
is_actual = models.BooleanField(default=False)
|
|
|
|
def __str__(self):
|
|
return f"Recommendation Playlist: {self.name}"
|
|
|
|
def switch_actual(self):
|
|
if not self.is_actual:
|
|
(RecommendationPlaylist.objects
|
|
.filter(is_actual=True)
|
|
.update(is_actual=False))
|
|
self.is_actual = True
|
|
self.save()
|