127 lines
4.4 KiB
Python
127 lines
4.4 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 ..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)
|
|
context['order'] = self.request.GET.get('order', 'latest')
|
|
context['canonical_url'] = self.request.build_absolute_uri(reverse('gallery:photos_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)
|
|
})
|
|
return context
|