from django.conf import settings from django.core.cache import cache from django.core.paginator import Paginator from django.db.models import Count, F, Q, Sum from django.http import JsonResponse from django.shortcuts import get_object_or_404, redirect from django.urls import reverse from django.views import View from django.views.generic import DetailView, ListView, TemplateView from ..models import Album, Photo, Redir class PhotosList(ListView): """Shows all public photos sorted by user-selected ordering.""" model = Photo paginate_by = 30 def get_queryset(self): ordering_options = { 'latest': '-taken_at', 'liked': '-likes', 'popular': '-views', 'favorite': '-is_favorite', } selected_order = self.request.GET.get('order', 'latest') order = ordering_options.get(selected_order, ordering_options['latest']) return Photo.objects.filter(album__is_public=True).order_by(order).select_related('album') def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # Canonical_url page = self.request.GET.get('page') if page and page != '1': canonical_url = f"{self.request.build_absolute_uri(reverse('gallery:photos_url'))}?page={page}" else: canonical_url = self.request.build_absolute_uri(reverse('gallery:photos_url')) context.update({ 'order': self.request.GET.get('order', 'latest'), 'canonical_url': canonical_url, }) return context class PhotoDetail(DetailView): """Shows a single photo and handles liking functionality.""" model = Photo slug_url_kwarg = 'photo_slug' template_name = 'gallery/photo_detail.html' def get_object(self, queryset=None): album_slug = self.kwargs.get('album_slug') photo_slug = self.kwargs.get('photo_slug') photo = get_object_or_404(Photo.objects.select_related('album'), slug=photo_slug, album__slug=album_slug) if photo.slug not in self.request.session: photo.add_view() self.request.session[photo.slug] = 0 return photo def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context.update({ 'next': self.object.get_next(), 'prev': self.object.get_prev(), 'canonical_url': self.request.build_absolute_uri(self.object.get_absolute_url()), 'liked': self.request.session.get(f"liked_{self.object.slug}", False) }) return context class PhotoLike(View): """Ajax like photo button.""" def get(self, request, *args, **kwargs): return JsonResponse({'error': 'This endpoint only supports POST requests.'}, status=405) def post(self, request, album_slug, photo_slug): photo = get_object_or_404(Photo.objects.select_related('album'), slug=photo_slug, album__slug=album_slug) session_key = f"liked_{photo.slug}" liked = request.session.get(session_key, False) if not liked: photo.likes += 1 if request.user.is_authenticated: photo.is_favorite = True request.session[session_key] = True status = "liked" else: photo.likes = max(0, photo.likes - 1) if request.user.is_authenticated: photo.is_favorite = False request.session[session_key] = False status = "unliked" photo.save() return JsonResponse({'success': True, 'likes': photo.likes, 'status': status}) class PhotoSlideshow(DetailView): """Slideshow.""" model = Photo slug_url_kwarg = 'photo_slug' template_name = 'gallery/photo_slideshow.html' def get_object(self, queryset=None): album_slug = self.kwargs.get('album_slug') photo_slug = self.kwargs.get('photo_slug') photo = get_object_or_404( Photo.objects.select_related('album'), slug=photo_slug, album__slug=album_slug ) if photo.slug not in self.request.session: photo.add_view() self.request.session[photo.slug] = 0 return photo def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) current_photo = self.object next_photo = current_photo.get_next() if not next_photo: next_photo = Photo.objects.filter(album=current_photo.album).order_by('taken_at').first() context.update({ 'next_photo': next_photo, 'liked': self.request.session.get(f"liked_{current_photo.slug}", False), 'canonical_url': self.request.build_absolute_uri(current_photo.get_slideshow_url()), }) return context