soundwave/backend/playlist/models_download.py

140 lines
4.2 KiB
Python
Raw Permalink Normal View History

"""Models for playlist download management"""
from django.db import models
from django.contrib.auth import get_user_model
from playlist.models import Playlist
User = get_user_model()
class PlaylistDownload(models.Model):
"""Track playlist download for offline playback"""
STATUS_CHOICES = [
('pending', 'Pending'),
('downloading', 'Downloading'),
('completed', 'Completed'),
('failed', 'Failed'),
('paused', 'Paused'),
]
playlist = models.ForeignKey(
Playlist,
on_delete=models.CASCADE,
related_name='downloads'
)
user = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='playlist_downloads'
)
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending')
# Progress tracking
total_items = models.IntegerField(default=0)
downloaded_items = models.IntegerField(default=0)
failed_items = models.IntegerField(default=0)
# Size tracking
total_size_bytes = models.BigIntegerField(default=0, help_text="Total size in bytes")
downloaded_size_bytes = models.BigIntegerField(default=0, help_text="Downloaded size in bytes")
# Download settings
quality = models.CharField(
max_length=20,
default='medium',
choices=[('low', 'Low'), ('medium', 'Medium'), ('high', 'High'), ('ultra', 'Ultra')]
)
# Timestamps
created_at = models.DateTimeField(auto_now_add=True)
started_at = models.DateTimeField(null=True, blank=True)
completed_at = models.DateTimeField(null=True, blank=True)
# Error tracking
error_message = models.TextField(blank=True)
# Download location
download_path = models.CharField(max_length=500, blank=True, help_text="Path to downloaded files")
class Meta:
ordering = ['-created_at']
unique_together = ('playlist', 'user')
indexes = [
models.Index(fields=['user', 'status']),
models.Index(fields=['playlist', 'status']),
]
def __str__(self):
return f"{self.user.username} - {self.playlist.title} ({self.status})"
@property
def progress_percent(self):
"""Calculate download progress percentage"""
if self.total_items == 0:
return 0
return (self.downloaded_items / self.total_items) * 100
@property
def is_complete(self):
"""Check if download is complete"""
return self.status == 'completed'
@property
def can_resume(self):
"""Check if download can be resumed"""
return self.status in ['paused', 'failed']
class PlaylistDownloadItem(models.Model):
"""Track individual audio items in playlist download"""
STATUS_CHOICES = [
('pending', 'Pending'),
('downloading', 'Downloading'),
('completed', 'Completed'),
('failed', 'Failed'),
('skipped', 'Skipped'),
]
download = models.ForeignKey(
PlaylistDownload,
on_delete=models.CASCADE,
related_name='items'
)
audio = models.ForeignKey(
'audio.Audio',
on_delete=models.CASCADE,
related_name='playlist_download_items'
)
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending')
position = models.IntegerField(default=0)
# Progress tracking
file_size_bytes = models.BigIntegerField(default=0)
downloaded_bytes = models.BigIntegerField(default=0)
# Timestamps
started_at = models.DateTimeField(null=True, blank=True)
completed_at = models.DateTimeField(null=True, blank=True)
# Error tracking
error_message = models.TextField(blank=True)
retry_count = models.IntegerField(default=0)
class Meta:
ordering = ['position']
unique_together = ('download', 'audio')
def __str__(self):
return f"{self.download.playlist.title} - {self.audio.title} ({self.status})"
@property
def progress_percent(self):
"""Calculate item download progress"""
if self.file_size_bytes == 0:
return 0
return (self.downloaded_bytes / self.file_size_bytes) * 100