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.
 
 

134 lines
5.1 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'
HADITH_CORRECTION = 'hadith_correction', 'Hadith Correction'
VIDEO = 'video', 'Video'
VIDEO_PLAYLIST = 'video_playlist', 'Video Playlist'
ARTICLE = 'article', 'Article'
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.hadis.models import Hadis
return Hadis.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()
elif service == cls.ServiceChoices.ARTICLE:
from apps.article.models import Article
return Article.objects.filter(id=content_id).exists()
elif service == cls.ServiceChoices.HADITH_CORRECTION:
from apps.hadis.models import HadisCorrection
return HadisCorrection.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'))
avg_rate = result['avg_rate']
return round(avg_rate, 2) if avg_rate is not None else None