Use ajax for like button

This commit is contained in:
Nyymix 2025-04-21 16:37:06 +03:00
parent 13fdbe4f4a
commit 47b543bbb3
3 changed files with 75 additions and 24 deletions

View file

@ -81,19 +81,16 @@
</div>
<div class="uk-grid-small" uk-grid>
<div class="uk-width-expand" uk-leader>Likes</div>
<div>{{ photo.likes }}</div>
<div id="like-count">{{ photo.likes }}</div>
</div>
<div class="uk-grid-small" uk-grid>
<div class="uk-width-expand" uk-leader>Download photo</div>
<div><a href="{{ photo.photo.url }}">{{ photo.width }}x{{ photo.height }}</a></div>
</div>
<div class="uk-grid-small" uk-grid>
<form action="{% url 'gallery:photo_url' photo.album.slug photo.slug %}" method="POST" class="uk-form">
{% csrf_token %}
<button type="submit" name="like" value="true" class="uk-button uk-button-primary">
<span uk-icon="icon: heart"></span> Like
<button id="like-button" class="uk-button uk-button-primary">
<span id="heart-icon" uk-icon="icon: heart"></span> <span id="like-text">Like</span>
</button>
</form>
</div>
</div>
</div>
@ -137,11 +134,46 @@
</div>
</div>
</div>
<script>
const likeBtn = document.getElementById('like-button');
const likeText = document.getElementById('like-text');
const heartIcon = document.getElementById('heart-icon');
const likeCount = document.getElementById('like-count');
likeBtn.addEventListener('click', function () {
fetch("{% url 'gallery:photo_like_url' photo.album.slug photo.slug %}", {
method: "POST",
headers: {
"X-CSRFToken": "{{ csrf_token }}",
"Content-Type": "application/json",
},
})
.then(response => response.json())
.then(data => {
if (data.success) {
likeCount.innerText = data.likes;
if (data.status === "liked") {
likeText.innerText = "Unlike";
heartIcon.setAttribute("style", "color: red");
} else {
likeText.innerText = "Like";
heartIcon.setAttribute("style", "color: inherit");
}
}
});
});
</script>
{% if liked %}
<script>
document.addEventListener("DOMContentLoaded", function() {
document.getElementById('like-text').innerText = "Unlike";
document.getElementById('heart-icon').setAttribute("style", "color: red");
});
</script>
{% endif %}
{% endblock %}

View file

@ -13,6 +13,7 @@ urlpatterns = [
path('about/', views.About.as_view(), name='about_url'),
path('search/', views.Search.as_view(), name='search_url'),
path('photostream/', views.PhotosList.as_view(), name='photos_url'),
path('like/<slug:album_slug>/<filename:photo_slug>', views.PhotoLike.as_view(), name='photo_like_url'),
path('albums/<path:album_slug>/<filename:photo_slug>', views.PhotoDetail.as_view(), name='photo_url'),
path('albums/<path:album_slug>/', views.AlbumDetail.as_view(), name='album_url'),
path('albums/', views.AlbumsList.as_view(), name='albums_url'),

View file

@ -2,8 +2,10 @@ from django.conf import settings
from django.core.cache import cache
from django.core.paginator import Paginator
from django.db.models import Count, Q, Sum
from django.shortcuts import get_object_or_404, redirect, render
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
@ -33,7 +35,7 @@ class AlbumsList(ListView):
cache.set(key, queryset, 60 * 5)
return queryset
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
page = int(self.request.GET.get('page', 1))
@ -43,7 +45,7 @@ class AlbumsList(ListView):
if page > 1:
canonical_url += f'?page={page}'
context['canonical_url'] = canonical_url
return context
@ -57,7 +59,7 @@ class AlbumDetail(DetailView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
#photos = self.object.photos.all().order_by('taken_at')
# photos = self.object.photos.all().order_by('taken_at')
photos = self.object.photos.all().select_related('album').order_by('taken_at')
paginator = Paginator(photos, 30)
@ -77,7 +79,6 @@ class AlbumDetail(DetailView):
return context
class PhotosList(ListView):
"""Shows all public photos sorted by user-selected ordering."""
model = Photo
@ -108,7 +109,7 @@ class PhotoDetail(DetailView):
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, slug=photo_slug, album__slug=album_slug)
# photo = get_object_or_404(Photo, slug=photo_slug, album__slug=album_slug)
photo = get_object_or_404(Photo.objects.select_related('album'), slug=photo_slug, album__slug=album_slug)
# Track views using session to avoid duplicate counts
@ -124,21 +125,37 @@ class PhotoDetail(DetailView):
"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
def post(self, request, *args, **kwargs):
photo = self.get_object()
if request.POST.get("like") == "true" and self.request.session.get(photo.slug) == 0:
photo.add_like()
self.request.session[photo.slug] = 1
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
photo.save()
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"
return redirect('gallery:photo_url', album_slug=self.kwargs['album_slug'], photo_slug=self.kwargs['photo_slug'])
photo.save()
return JsonResponse({'success': True, 'likes': photo.likes, 'status': status})
class Search(TemplateView):
@ -175,6 +192,7 @@ class Search(TemplateView):
class About(TemplateView):
"""Static about page."""
template_name = "gallery/about.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['canonical_url'] = self.request.build_absolute_uri(reverse('gallery:about_url'))