Почему 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)
Вернуться на верх