I want to check if the post is liked/not by the current user. If it is liked, then there should be a filled heart, otherwise empty heart. What I am trying to do is to implement a typical ‘like’ functionality of Instagram. I am trying to approach in this way, that on reloading the page, every post gets updated and their ‘like’ button as well according to as they have liked it or not. Then, if a user clicks on a like button, then in frontend ‘like’ button will change without referring to the backend. At the same time, the request to change the like in the backend has already been sent by ajax. How do I achieve this? And is there an even better way to do this?
feed.html:-
{% extends "user/base.html" %}
{% load static %}
{% block content %}
<div class="flex my-8 justify-center">
<h2 class="text-4xl">All Posts</h2>
</div>
<div class="grid grid-cols-1">
{% for post in posts %}
<div class="flex justify-center">
<div class="mb-20 md:mx-60 lg:mx-80">
<div class="flex">
<a href="#">
<div class="user-container h-12 w-12 mb-2 flex">
{% if post.user.profile.image %}
<img class="rounded-full" src="{{post.user.profile.image.url}}" alt="">
{% endif %}
<div class="px-3 flex items-center italic"><strong>{{post.user}}</strong></div>
</div>
</a>
</div>
<div class="rounded-md overflow-hidden">
<img class="h-96 w-96 shadow-lg" src={{post.image.url}} alt="">
</div>
<div>
<div class="icon-container mt-1 flex items-center gap-3">
<a class="btn-like" id={{post.id}}>
{% if post.liked_by.filter(id=request.user.id).exists() %}
<img class="w-8 h-8" src={% static 'posts/heart.svg' %} alt="">
{% else %}
<img class="w-8 h-8" src={% static 'posts/heart-filled.svg' %} alt="">
{% endif %}
</a>
<img class="w-7 h-7" src={% static 'posts/comment.svg' %} alt="">
<img class="w-8 h-8" src={% static 'posts/share.svg' %} alt="">
</div>
</div>
<div class="break-word w-96">
<strong class="text-lg">{{post.title}}</strong>
<p>{{post.caption}}</p>
</div>
</div>
</div>
{% endfor %}
</div>
<script type="text/javascript">
window.CSRF_TOKEN = "{{csrf_token}}"
$('.btn-like').on('click', function () {
let post_id = parseInt(this.id);
$('#' + post_id).children('img').attr('src', function (index, attr) {
return attr == '/static/posts/heart.svg' ? null : '/static/posts/heart.svg';
});
$.ajax({
method: "POST",
url: "/posts/like/",
data: {
post_id: post_id,
csrfmiddlewaretoken: window.CSRF_TOKEN
}
})
})
</script>
{% endblock content %}
views.py:-
from django.shortcuts import render, get_object_or_404, redirect
from .forms import PostForm
from django.contrib.auth.decorators import login_required
from .models import Post
# Create your views here.
@login_required
def create_post(request):
if request.method == 'POST':
form = PostForm(data=request.POST, files=request.FILES)
if form.is_valid():
new_item = form.save(commit=False)
new_item.user = request.user
new_item.save()
else:
form = PostForm()
return render(request, 'posts/create.html', {'form': form})
@login_required
def my_posts(request):
current_user = request.user
posts = Post.objects.filter(user=current_user)
profile = current_user.profile
return render(request, 'user/index.html', {'posts': posts, 'profile': profile})
def feed(request):
posts = Post.objects.all().order_by('-created')
return render(request, 'posts/feed.html', {'posts': posts})
@login_required
def like_post(request):
post_id = request.POST.get('post_id')
post = get_object_or_404(Post, id=post_id)
if post.liked_by.filter(id=request.user.id).exists():
post.liked_by.remove(request.user)
else:
post.liked_by.add(request.user)
return redirect('feed')