Почему Ajax с Django дает мне двойные значения для увеличения и уменьшения значений like_count?
Так я делал кнопку like с помощью Ajax, и когда я ставлю лайк или удаляю лайк, мне нужно, чтобы like_count
уменьшалось и чтобы это происходило в реальном времени, но происходит то, что когда я нажимаю кнопку like, она увеличивает или уменьшает 2 значения, и я не знаю почему.
Вот код.
Модели:
class Post(models.Model):
favs = models.ManyToManyField(User, blank=True, related_name='favs')
likes_count = models.IntegerField(default=0)
Просмотров:
class AddLike(LoginRequiredMixin, View):
def post(self, request, pk, *args, **kwargs):
post = Post.objects.get(pk=pk)
is_like = False
for like in post.likes.all():
if like == request.user:
is_like = True
break
if not is_like:
post.likes.add(request.user)
post.likes_count = post.likes_count +1
if is_like:
post.likes.remove(request.user)
post.likes_count = post.likes_count -1
post.save()
next = request.POST.get('next', '/')
return HttpResponseRedirect(next)
HTML:
<form method="POST" id="like-post">
{% csrf_token %}
<input type="hidden" name="next" value="{{ request.path }}">
<input type="hidden" name="pk" value="{{ post.pk }}">
<input type="hidden" name="like-count" value="{{ post.likes_count }}">
<button style="background-color: transparent; border: none; box-shadow: none;" type="submit">
<span id="count{{ post.pk }}" >{{ post.likes_count }}</span>
{% if request.user in post.likes.all %}
<i id="no-like{{ post.pk }}" style="color:gray ;display: none;" class="fa-solid fa-champagne-glasses"></i>
<i id="liked{{ post.pk }}" style="color:green ;" class="fa-solid fa-champagne-glasses"></i>
{% else %}
<i id="liked{{ post.pk }}" style="color:green ;display: none;" class="fa-solid fa-champagne-glasses"></i>
<i id="no-like{{ post.pk }}" style="color:gray ; " class="fa-solid fa-champagne-glasses"></i>
{% endif %}
</button>
</form>
<
$(document).on('submit','#like-post',function(e){
e.preventDefault();
pkey = $(this).children('input')[2].value;
$.ajax({
type:'POST',
url:"/social/post/"+pkey+"/like",
data:{
csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val(),
},
success: function(response){
console.log(pkey, count);
},
error: function(response){
console.log(pkey);
}
});
count = parseInt($(this).children('input')[3].value);
if (document.getElementById("no-like" + pkey).style.display == "none"){
document.getElementById("no-like" + pkey).style.display = "block"
document.getElementById("liked" + pkey).style.display = 'none';
document.getElementById('count'+pkey).innerHTML = count - 1;
} else {
document.getElementById("no-like" + pkey ).style.display = "none";
document.getElementById("liked" + pkey).style.display = 'block';
document.getElementById('count'+pkey).innerHTML = count + 1;
}
});
Помогите мне кто-нибудь!
Потому что вы отправляете два POST-запроса. Первый в вашей HTML форме, а второй с помощью AJAX. Вы не использовали условие if в своем представлении для распознавания ajax-запроса
удалите атрибут method
из элемента формы и измените тип кнопки на button
с submit
и присвойте кнопке id
<form id="like-post">
{% csrf_token %}
<input type="hidden" name="next" value="{{ request.path }}">
<input type="hidden" name="pk" value="{{ post.pk }}">
<input type="hidden" name="like-count" value="{{ post.likes_count }}">
<button style="background-color: transparent; border: none; box-shadow: none;" type="button" id="submit_btn">
<span id="count{{ post.pk }}" >{{ post.likes_count }}</span>
{% if request.user in post.likes.all %}
<i id="no-like{{ post.pk }}" style="color:gray ;display: none;" class="fa-solid fa-champagne-glasses"></i>
<i id="liked{{ post.pk }}" style="color:green ;" class="fa-solid fa-champagne-glasses"></i>
{% else %}
<i id="liked{{ post.pk }}" style="color:green ;display: none;" class="fa-solid fa-champagne-glasses"></i>
<i id="no-like{{ post.pk }}" style="color:gray ; " class="fa-solid fa-champagne-glasses"></i>
{% endif %}
</button>
</form>
в JS:
// Detect submit by click instead of submit event
$(document).on('click','#submit_btn',function(e){ //important
e.preventDefault();
pkey = $(this).children('input')[2].value;
$.ajax({
type:'POST',
url:"/social/post/"+pkey+"/like",
//... rest of it
Решение 2
Определите ajax-запросы для ограничения запроса html-формы ( это может быть причиной низкой производительности, поскольку вы все равно отправляете два запроса на почту) в js:
$(document).on('submit','#like-post',function(e){
e.preventDefault();
pkey = $(this).children('input')[2].value;
$.ajax({
type:'POST',
url:"/social/post/"+pkey+"/like",
headers: {
"X-Requested-With": "XMLHttpRequest",
},
data:{
csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val(),
},
success: function(response){
console.log(pkey, count);
},
error: function(response){
console.log(pkey);
}
});
count = parseInt($(this).children('input')[3].value);
if (document.getElementById("no-like" + pkey).style.display == "none"){
document.getElementById("no-like" + pkey).style.display = "block"
document.getElementById("liked" + pkey).style.display = 'none';
document.getElementById('count'+pkey).innerHTML = count - 1;
} else {
document.getElementById("no-like" + pkey ).style.display = "none";
document.getElementById("liked" + pkey).style.display = 'block';
document.getElementById('count'+pkey).innerHTML = count + 1;
}
});
в просмотре:
class AddLike(LoginRequiredMixin, View):
def post(self, request, pk, *args, **kwargs):
# request.is_ajax() is deprecated since django 3.1
is_ajax = request.headers.get('X-Requested-With') == 'XMLHttpRequest'
if is_ajax:
post = Post.objects.get(pk=pk)
is_like = False
for like in post.likes.all():
if like == request.user:
is_like = True
break
if not is_like:
post.likes.add(request.user)
post.likes_count = post.likes_count +1
if is_like:
post.likes.remove(request.user)
post.likes_count = post.likes_count -1
post.save()
next = request.POST.get('next', '/')
return HttpResponseRedirect(next)