from django.db import models from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType from django.utils import timezone from django.db.models import Count from django.conf import settings class PageView(models.Model): content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, related_name='page_views') object_id = models.PositiveIntegerField() content_object = GenericForeignKey('content_type', 'object_id') timestamp = models.DateTimeField(auto_now_add=True, db_index=True) ip_address = models.GenericIPAddressField() user_agent = models.CharField(max_length=512, blank=True) class Meta: indexes = [ models.Index(fields=['timestamp']), models.Index(fields=['content_type', 'object_id']), ] @classmethod def get_trending_items(cls, model_class, hours=24, limit=10): """Get trending items of a specific model class based on views in last X hours. Args: model_class: The model class to get trending items for (e.g., Park, Ride) hours (int): Number of hours to look back for views (default: 24) limit (int): Maximum number of items to return (default: 10) Returns: QuerySet: The trending items ordered by view count """ content_type = ContentType.objects.get_for_model(model_class) cutoff = timezone.now() - timezone.timedelta(hours=hours) # Query through the ContentType relationship item_ids = cls.objects.filter( content_type=content_type, timestamp__gte=cutoff ).values('object_id').annotate( view_count=Count('id') ).filter( view_count__gt=0 ).order_by('-view_count').values_list('object_id', flat=True)[:limit] # Get the actual items in the correct order if item_ids: # Convert the list to a string of comma-separated values id_list = list(item_ids) # Use Case/When to preserve the ordering from django.db.models import Case, When preserved = Case(*[When(pk=pk, then=pos) for pos, pk in enumerate(id_list)]) return model_class.objects.filter(pk__in=id_list).order_by(preserved) return model_class.objects.none()