muistox/gallery/views/photo.py
2025-08-05 21:43:56 +03:00

157 lines
5.1 KiB
Python

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 gallery.utils import build_canonical_url
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(self, request, *args, **kwargs):
# Aseta järjestys heti pyynnön käsittelyn alussa
self.order = self.request.GET.get('order', 'latest')
return super().get(request, *args, **kwargs)
def get_queryset(self):
ordering_options = {
'latest': '-taken_at',
'liked': '-likes',
'popular': '-views',
'favorite': '-is_favorite',
}
order_by = ordering_options.get(self.order, ordering_options['latest'])
return Photo.objects.filter(album__is_public=True).order_by(order_by).select_related('album')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
page_obj = context.get('page_obj')
# Canonical_url
canonical_url = build_canonical_url(
self.request,
reverse('gallery:photos_url'),
params={'page': page_obj.number, 'order': self.order}
)
context.update({
'order': self.order,
'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__iexact=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)
# Canonical_url
canonical_url = build_canonical_url(
self.request,
self.object.get_absolute_url()
)
context.update({
'next': self.object.get_next(),
'prev': self.object.get_prev(),
'canonical_url': canonical_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()
# Canonical_url
canonical_url = build_canonical_url(
self.request,
current_photo.get_slideshow_url()
)
context.update({
'next_photo': next_photo,
'liked': self.request.session.get(f"liked_{current_photo.slug}", False),
'canonical_url': canonical_url,
})
return context