Как отобразить нужные кнопки (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 %}