Julio Cesar
Julio Cesar

Reputation: 265

Forbidden (CSRF token missing or incorrect.) | Django and AJAX

:(

I am making ajax requests, but I get this error:

Forbidden (CSRF token missing or incorrect.): /manager/ajax/
[23/Jun/2020 00:00:46] "POST /manager/ajax/ HTTP/1.1" 403 2517
[23/Jun/2020 00:01:18] "GET /manager/test/update/3/ HTTP/1.1" 200 10249
Forbidden (CSRF token missing or incorrect.): /manager/ajax/
[23/Jun/2020 00:01:18] "POST /manager/ajax/ HTTP/1.1" 403 2517
[23/Jun/2020 00:01:22] "GET /manager/test/update/3/ HTTP/1.1" 200 10249
Forbidden (CSRF token missing or incorrect.): /manager/ajax/
[23/Jun/2020 00:01:23] "POST /manager/ajax/ HTTP/1.1" 403 2517

JS:

function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = cookies[i].trim();
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

var csrftoken = getCookie('csrftoken');

fetch('/manager/ajax/', {
    method: 'POST',
    body: JSON.stringify({
        csrfmiddlewaretoken: csrftoken,
        title: 'hello!!!! :(',
    }),

    headers: {
        "Content-Type": "application/x-www-form-urlencoded"
    }
})
.then(response => response.json())
.then(json => console.log(json))

My view:

def delete_exam_question(request):
    print(request.method)

    if request.is_ajax:
        print(request.POST)
        #exam_question = ExamQuestion.objects.get(title = request.POST.get('title'))
        #exam_question.delete()

    return JsonResponse({'deleted': True})

I tried to fix it like in this question ("application/x-www-form-urlencoded"), I already tried indicating "application/json", but it does not work... :(

I pass the token (csrftoken), but it still doesn't work, I've tried everything, but I can't get it to work.


UPDATE:

("Content-Type" => "application/x-www-form-urlencoded")

Decorate the view, with the decorator csrf_exempt. And the POST data are:

<QueryDict: {'{"csrfmiddlewaretoken":"4gTL9H17LIgTFc3HseYFuT6JQMbkEHxiuGXVxu9WWKTgN0gVmUtJJPDgwem0zj4U","title":"holaaa"}': ['']}>

That's why he gave me the error, but this, is very very rare. And I don't know how to correct it, any ideas? I don't know much JavaScript.

I changed the Conten-Type, to "application/json", and the POST data are:

<QueryDict: {}>

but, i print request.body, and printed that:

b'{"csrfmiddlewaretoken":"4gTL9H17LIgTFc3HseYFuT6JQMbkEHxiuGXVxu9WWKTgN0gVmUtJJPDgwem0zj4U","title":"holaaa"}'

what's going on? :(

Upvotes: 0

Views: 2793

Answers (1)

minglyu
minglyu

Reputation: 3327

Take a look of the source code below, you need explicitly tell Django this request if called using XMLHttpRequest. better avoid to use is_ajax to detect ajax, since it will be deprecated in future versions

def is_ajax(self):
    warnings.warn(
        'request.is_ajax() is deprecated. See Django 3.1 release notes '
        'for more details about this deprecation.',
         RemovedInDjango40Warning,
         stacklevel=2,
      )
     return self.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'

Add these lines in your header, use of X-CSRFToken is prefered for ajax request since it also support other request method like DELETE, PUT, etc

# django internllay change '-' to '_' and add prefix HTTP in front of the value
# so 'X-Requested-With' becomes HTTP_X_REQUESTED_WITH, which is used by is_ajax function 
{
   'X-Requested-With': 'XMLHttpRequest',
   'X-CSRFToken': <your_csrftoken_value>
}

EDIT

$('#sub-btn').click(function(e){ 
    e.preventDefault();
    $.ajax( 
        { 
        type:"POST", 
        beforeSend: function (xhr) {
            xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
            xhr.setRequestHeader('X-CSRFToken', <your_csrftoken_value>);
        },
        url: <your_url>, 
        data: {test: 'test'},
        success: function(data){ 
           console.log(data)
        }
    });
})  

Also, if you use jQuery and send data using this format, you could receive data in request.POST

Upvotes: 2

Related Questions