0

I have this ajax like vote on my article model:

@csrf_exempt
@login_required
def like(request):
    args = {}
    if request.method == 'POST':
        user = request.POST.get('user')
        lu= request.user 
        post_id = int(request.POST.get('post_id'))
        try:
            liked_article = Article.objects.get(id = post_id)
        except:
            liked_article = None  

        if ArticleLike.objects.filter(liker=lu.id, article=post_id).exists():

            liked_article.likes -=1
            liked_article.save()
            ArticleLike.objects.filter(article=post_id, liker=lu.id).delete()


        else:            
            liked_article.likes +=1
            liked_article.save()
            newliker = ArticleLike(article=post_id, liker=lu.id)
            newliker.save()          

    args.update(csrf(request))
    args['likes'] = str(liked_article.likes)
    return render(request, 'ajax_like.html', args)   

Here is the ajax snippet:

$(function(){
$('#like').click(function(){
      $.ajax({
               type: "POST",
               url: "/article/like/",
               data: {
               'post_id': $(this).attr('name'), 
               'csrfmiddlewaretoken': '{{csrf_token}}'
               },
               success: likeSuccess,
               dataType: 'html'
                }); 
    });

});
function likeSuccess(data, textStatus, jqXHR)
{
    $('#like_count').html(data);
}

and ajax_lik.html

<p id="like_count">
{% if likes > 0 %}
{{likes}}
</p>
{% else %}
wow
</i>

{% endif %} The view works perfectly well with @csrf_exempt decorator active, but with csrf, I get 403 Forbidden error.

I tried different tweaks but could not figure out how solve this, so I appreciate your help.

Jand
  • 2,527
  • 12
  • 36
  • 66

1 Answers1

0

If you are using a @csrfexempt decorator then you don't need to send a csrf_token. BTW, csrf_token shouldn't be part of the POST data,

data: {
       'post_id': $(this).attr('name'), 
       'csrfmiddlewaretoken': '{{csrf_token}}'
      }

it should be in the request's header "X-CSRFToken".

Here a little example to set custom headers to an ajax request using jquery (docs here):

$.ajax({
         url: "/article/like/",
         data: { post_id: $(this).attr('name') },
         type: "POST",
         beforeSend: function(xhr){xhr.setRequestHeader('X-CSRFToken', "{{csrf_token}}");},
         success: likeSuccess,
         dataType: 'html'
      });

You can see Django's docs for this here

Gocht
  • 9,924
  • 3
  • 42
  • 81
  • I added `@csrf_exempt` as the last resort, because I could not make csrf working. Could you please give a complete example of the ajax snippet with correct csrf call? – Jand Nov 04 '15 at 22:17
  • It should be in POST data, see answer here: http://stackoverflow.com/questions/8614947/jquery-and-django-csrf-token – Shang Wang Nov 04 '15 at 22:18
  • @ShangWang See the comments there. I recommend use it in headers, that's why my answer. – Gocht Nov 04 '15 at 22:22
  • What should I put in place of ``? It gives a syntax error. – Jand Nov 04 '15 at 22:29
  • @Jand You should replace `` with the actual token. – Gocht Nov 04 '15 at 22:30
  • sorry, now it gives this syntax error: `Unexpected end of input` – Jand Nov 04 '15 at 22:33
  • [here](http://stackoverflow.com/questions/33224870/django-csrf-verification-for-ajax-requests-working-in-chrome-but-not-firefox?rq=1) you will find another example if you need it. – Gocht Nov 04 '15 at 22:36
  • Sure here it is: $(function(){ $('#like').click(function(){ var csrf_token = '{{ csrf_token }}'; $.ajax({ url: "/article/like/", data: { post_id: $(this).attr('name') }, type: "POST", beforeSend: function(xhr){xhr.setRequestHeader('X-CSRFToken', csrf_token);}, success: likeSuccess, dataType: 'html' }); }); function likeSuccess(data, textStatus, jqXHR) { $('#like_count').html(data); } – Jand Nov 04 '15 at 22:39
  • I don't see any problem, please try giving the `{{ csrf_token }}` in the `beforeSend` function. – Gocht Nov 04 '15 at 22:42
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/94255/discussion-between-jand-and-gocht). – Jand Nov 04 '15 at 22:44