Как отобразить нужные кнопки (Like или Unlike) в посте на основе выбора пользователя с помощью Javascript в веб-приложении?

Я работаю над веб-приложением, в котором пользователь имеет возможность поставить лайк или не поставить лайк сообщению, опубликованному другим пользователем. Я создал кнопку и написал функцию Javascript для изменения текста внутри кнопки в зависимости от выбора пользователя. Если пользователь нажимает кнопку Like, она меняется на Unlike и наоборот.

Вот мой код:

models.py

class Post(models.Model):
    """ Model representing a post. """
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    content = models.TextField()
    timestamp = models.DateTimeField(auto_now_add=True)
    no_of_likes = models.IntegerField(default=0)

    def __str__(self):
        return f"Post {self.id} by {self.user.username} on {self.timestamp}"
    
class Like(models.Model):
    """ Model representing a like. """
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    timestamp = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.user} likes {self.post}"

urls.py

path("", views.index, name="index"),
path("like/<int:post_id>", views.like, name="like"),
path("unlike/<int:post_id>", views.unlike, name="unlike"),

views.py

def index(request):
    """ Home page. """
    posts = Post.objects.all().order_by('-timestamp')
    paginator = Paginator(posts, 5)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    likes = Like.objects.all()
    
    # List of post ids.
    liked_posts = Like.objects.filter(user=request.user).values_list('post', flat=True)
    liked_posts = list(liked_posts)
    
    return render(request, "network/index.html", {
        "posts": posts,
        "page_obj": page_obj,
        "likes": likes,
        "liked_posts": liked_posts,              
    })

@login_required
def like(request, post_id):
    
    post = Post.objects.get(pk=post_id)
    user = User.objects.get(pk=request.user.id)
    like = Like.objects.create(user=user, post=post)
    like.save()
    
    post.no_of_likes = Like.objects.filter(post=post).count()
    post.save()
    return JsonResponse({"message": "successfully liked", "no_of_likes": post.no_of_likes})

@login_required   
def unlike(request, post_id):
    
    post = Post.objects.get(pk=post_id)
    user = User.objects.get(pk=request.user.id)
    like = Like.objects.filter(user=user, post=post)
    like.delete()

    post.no_of_likes = Like.objects.filter(post=post).count()
    post.save()
    return JsonResponse({"message": "successfully unliked", "no_of_likes": post.no_of_likes})

index.html с Javascript

<!--Create button-->
<button type="button" class="btn btn-success like" id="like{{ post.id }}" onclick="toggleLike('{{ post.id }}')">Like</button>

// JavaScript
    function toggleLike(postId) {
        var likeButton = document.getElementById('like' + postId);

        if (likeButton.innerText === 'Like') {
            // Change button to Unlike
            likeButton.innerText = 'Unlike';
            likeButton.style.background = '#dc3545'; // Change button color to red
            // Update counter
            fetch(`/like/${postId}`, {
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                    "X-CSRFToken": "{{ csrf_token }}",
                },
            })
            .then(response => response.json())
            .then(data => {
                document.querySelector("#no-of-likes" + postId ).innerHTML = data.no_of_likes + " likes";
            })
        } else {
            // Change button to Like
            likeButton.innerText = 'Like';
            likeButton.style.background = ''; // Reset button color
            // Update counter
            fetch(`/unlike/${postId}`, {
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                    "X-CSRFToken": "{{ csrf_token }}",
                },
            })
            .then(response => response.json())
            .then(data => {
                document.querySelector("#no-of-likes" + postId).innerHTML = data.no_of_likes + " likes";
            })
        }
    }

Когда я обновляю страницу, все кнопки меняются на Like, хотя пользователю понравились некоторые посты, где должны отображаться кнопки Unlike.

Я попытался исправить это, написав следующий код, но это не решило проблему.

document.addEventListener('DOMContentLoaded', function() {
        const buttons = document.querySelectorAll(".like");
         
        buttons.forEach(button => {
            const postId = button.getAttribute('id').replace('like', '');
            
            if ('{{ liked_posts }}'.includes(postId)) {
                button.innerText = "Unlike";
                button.style.background = "red";
            } else {
                button.innerText = "Like";
                button.style.background = "green";
            }            
        });
    })

С этим новым кодом я получаю странную ошибку, когда если мне нравится только пост № 12 одного другого пользователя, то посты № 1 и 2 этого же пользователя также показывают кнопки Unlike. А если мне нравится пост № 11 этого другого пользователя, то пост № 1 также отображает кнопку Unlike. Я думаю, что это как-то связано с функцией .include(), но не могу понять, в чем дело. Есть предложения, как исправить эту ошибку? Заранее спасибо!

Вы создаете метод в файле models.py и делаете его свойством с помощью декоратора @property, после чего вы можете получить доступ к свойству в вашем шаблоне

#models.py

class Post(models.Model):
    """ Model representing a post. """
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    content = models.TextField()
    timestamp = models.DateTimeField(auto_now_add=True)
    no_of_likes = models.IntegerField(default=0)

    def __str__(self):
        return f"Post {self.id} by {self.user.username}"


    @property
    def has_liked_by(self, user):
      return Like.objects.filter(user=user, post=self).exists()

#products.html

{% if post.has_liked_by user %}
  <span class="liked">You liked this post.</span>
  <button type="button" onclick="unlikePost({{ post.id }})">Unlike</button>
{% else %}
  <button type="button" onclick="likePost({{ post.id }})">Like</button>
{% endif %}
Вернуться на верх