You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
125 lines
4.6 KiB
125 lines
4.6 KiB
|
|
from django.db import models
|
|
from django.contrib.auth import get_user_model
|
|
from django.core.validators import MinValueValidator, MaxValueValidator
|
|
from django.db.models import Avg
|
|
|
|
User = get_user_model()
|
|
|
|
class Rate(models.Model):
|
|
"""
|
|
Rate model for different services like library, podcast, hadith, and video.
|
|
Users can rate content from 1 to 5.
|
|
"""
|
|
|
|
class ServiceChoices(models.TextChoices):
|
|
LIBRARY = 'library', 'Library'
|
|
PODCAST = 'podcast', 'Podcast'
|
|
PODCAST_PLAYLIST = 'podcast_playlist', 'Podcast Playlist'
|
|
HADITH = 'hadith', 'Hadith'
|
|
VIDEO = 'video', 'Video'
|
|
VIDEO_PLAYLIST = 'video_playlist', 'Video Playlist'
|
|
|
|
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='rates', verbose_name='User')
|
|
service = models.CharField(max_length=20, choices=ServiceChoices.choices, verbose_name='Service')
|
|
content_id = models.PositiveIntegerField(verbose_name='Content ID')
|
|
rate = models.PositiveSmallIntegerField(
|
|
validators=[MinValueValidator(1), MaxValueValidator(5)],
|
|
verbose_name='Rate'
|
|
)
|
|
status = models.BooleanField(default=True, verbose_name='Status')
|
|
created_at = models.DateTimeField(auto_now_add=True, verbose_name='Created At')
|
|
updated_at = models.DateTimeField(auto_now=True, verbose_name='Updated At')
|
|
|
|
class Meta:
|
|
verbose_name = 'Rate'
|
|
verbose_name_plural = 'Rates'
|
|
unique_together = ('user', 'service', 'content_id')
|
|
|
|
def __str__(self):
|
|
return f"{self.user.username} - {self.get_service_display()} - {self.content_id} - {self.rate}"
|
|
|
|
@classmethod
|
|
def get_user_rate(cls, user, service, content_id):
|
|
"""
|
|
Get the rate information for a specific content by the user.
|
|
|
|
Args:
|
|
user: User instance
|
|
service: Service name (library, podcast, hadith, video)
|
|
content_id: ID of the content
|
|
|
|
Returns:
|
|
Dictionary containing:
|
|
- is_rated: Boolean indicating if the content is rated by the user
|
|
- rate: The rate value given by the user (1-5) or None if not rated
|
|
"""
|
|
try:
|
|
rate_obj = cls.objects.get(
|
|
user=user,
|
|
service=service,
|
|
content_id=content_id,
|
|
status=True
|
|
)
|
|
return {
|
|
'is_rated': True,
|
|
'rate': rate_obj.rate
|
|
}
|
|
except cls.DoesNotExist:
|
|
return {
|
|
'is_rated': False,
|
|
'rate': None
|
|
}
|
|
|
|
@classmethod
|
|
def validate_content_exists(cls, service, content_id):
|
|
"""
|
|
Validate if content with the given ID exists in the specified service.
|
|
|
|
Args:
|
|
service: Service name (library, podcast, hadith, video)
|
|
content_id: ID of the content to validate
|
|
|
|
Returns:
|
|
Boolean indicating if the content exists
|
|
"""
|
|
if service == cls.ServiceChoices.LIBRARY:
|
|
from apps.library.models import Book
|
|
return Book.objects.filter(id=content_id).exists()
|
|
elif service == cls.ServiceChoices.PODCAST:
|
|
from apps.podcast.models import Podcast
|
|
return Podcast.objects.filter(id=content_id).exists()
|
|
elif service == cls.ServiceChoices.PODCAST_PLAYLIST:
|
|
from apps.podcast.models import PodcastPlaylist
|
|
return PodcastPlaylist.objects.filter(id=content_id).exists()
|
|
elif service == cls.ServiceChoices.HADITH:
|
|
from apps.hadith.models import Hadith
|
|
return Hadith.objects.filter(id=content_id).exists()
|
|
elif service == cls.ServiceChoices.VIDEO:
|
|
from apps.video.models import Video
|
|
return Video.objects.filter(id=content_id).exists()
|
|
elif service == cls.ServiceChoices.VIDEO_PLAYLIST:
|
|
from apps.video.models import VideoPlaylist
|
|
return VideoPlaylist.objects.filter(id=content_id).exists()
|
|
return False
|
|
|
|
@classmethod
|
|
def get_average_rate(cls, service, content_id):
|
|
"""
|
|
Get the average rate for a specific content.
|
|
|
|
Args:
|
|
service: Service name (library, podcast, hadith, video)
|
|
content_id: ID of the content
|
|
|
|
Returns:
|
|
Float representing the average rate (1-5) or None if no rates
|
|
"""
|
|
result = cls.objects.filter(
|
|
service=service,
|
|
content_id=content_id,
|
|
status=True
|
|
).aggregate(avg_rate=Avg('rate'))
|
|
|
|
return result['avg_rate']
|
|
|