简体   繁体   中英

Can not get comment id with AJAX in django

I'm fighting with this problem during several days and can not find the solution for my case. I'm trying to make system of likes without refreshing the page. In synchronous mode system of likes and dislikes works fine, but when I'm trying to add AJAX, I'm getting 405 and only one last comment is working for one click, I understand problem that Ajax doesn't understand django urls with id or pk like my variant {% url 'store:like' comment.pk %}, but how it can be solved?

There is this part from the template:

{% for comment in comments %}
       <h6 class="card-header">
       {{ comment.author }}<small> добавлен {{ comment.created_at|date:'M d, Y H:i' }} </small>
       </h6>
        <div class="card-body">
        <h4>{{ comment }}</h4>
        <form id="like" method="POST" data-url="{% url 'store:like' comment.pk %}">
                    {% csrf_token %}
                    <input type="hidden" value="{{comment.pk}}" name="id">
                    <input type="hidden" name="next" value="{{ request.path }}">
                    <button style="background-color: transparent; border: none; box-shadow: none;" type="submit">
                        <a class="btn btn-success" id="like"> Likes {{ comment.likes.all.count }}</a>
                    </button>
                </form>
        

        </div>
        {% empty %}
        <p>Для данного товара  ещё нет комментариев.</p>

        {% endfor %}

my ajax call in the same template:

<script type="text/javascript">
    $(document).ready(function(){

        var endpoint = $("#like").attr("data-url")

  $('#like').submit(function(e){

            e.preventDefault();

            var serializedData = $(this).serialize();
      $.ajax({
               type: 'POST',
               url: endpoint,
               data: serializedData,
               success: function(response) {
                     $('#main').load(' #main', function(){
           /// can add another function here

      });
                },
                error: function(rs, e) {
                       alert(rs.responseText);
                }
          });
    })

    });

This part from urls:

path('products/<int:pk>/like/', addlike, name='like'),

View for like:

def addlike(request, *args, **kwargs):

        #is_ajax = request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
        #if request.method == 'POST' and is_ajax:

            pk = request.POST.get('id')
            post = Comment.objects.get(pk=pk)


            is_dislike = False

            for dislike in post.dislikes.all():
                if dislike == request.user:
                    is_dislike = True
                    break

            if is_dislike:
                post.dislikes.remove(request.user)

            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)

            if is_like:
                post.likes.remove(request.user)


            next = request.POST.get('next', '/')
            return HttpResponseRedirect(next)
            #return JsonResponse({"success": True}, status=200)

        #else:
            #return JsonResponse({"success": False}, status=400)

How to force AJAX to call in pk what I need?

I think you should send the csrf_token with the ajax request add headers: { "X-CSRFToken": token } to your ajax request, "token is the csrf_token" or add @csrf_exempt decorator to your function but it will keep your view unsafe against CSRF attacks.

you can find more info here https://docs.djangoproject.com/en/4.0/ref/csrf/

Remove the data-url and set the action attribute because when you click the submit button, by default this POST request will be sent to the current URL and you will receive the 405 status code, but if you set action this POST request will be sent to the like url:

<form id="like" method="POST" action="{% url 'store:like' comment.pk %}">
    {% csrf_token %}
     <input type="hidden" value="{{comment.pk}}" name="id">
     <input type="hidden" name="next" value="{{ request.path }}">
     <button style="background-color: transparent; border: none; box-shadow: none;" type="submit">
     <a class="btn btn-success" id="like"> Likes {{ comment.likes.all.count }}</a>
     </button>
</form>
        

And in js you can get the URL like this

var endpoint = $(this).attr('action');

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM