为什么Ajax和Django会给我双倍的值来增加和减少like_count的值



所以我用Ajax制作了一个类似按钮,当我喜欢或删除类似时,我需要like_count来减少并实时制作,但实际情况是,当我单击类似按钮时,它会增加或减少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>

Ajax:

$(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属性,将按钮类型从submit更改为button,并为按钮提供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表单请求(这可能会导致性能不佳,因为您仍然发送两个post请求(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)