403 Forbidden error when making an ajax Post request in Django framework
Solution 1
Because you did not post the csrfmiddlewaretoken, so Django forbid you. this document can help you.
Solution 2
For the lazy guys:
First download cookie: http://plugins.jquery.com/cookie/
Add it to your html:
<script src="{% static 'designer/js/jquery.cookie.js' %}"></script>
Now you can create a working POST request:
var csrftoken = $.cookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
$.ajax(save_url, {
type : 'POST',
contentType : 'application/json',
data : JSON.stringify(canvas),
success: function () {
alert("Saved!");
}
})
Solution 3
The fastest solution if you are not embedding js into your template is:
Put <script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
before your reference to script.js file in your template, then add csrfmiddlewaretoken
into your data
dictionary:
$.ajax({
type: 'POST',
url: somepathname + "do_it/",
data: {csrfmiddlewaretoken: window.CSRF_TOKEN},
success: function() {
console.log("Success!");
}
})
If you do embed your js into the template, it's as simple as: data: {csrfmiddlewaretoken: '{{ csrf_token }}'}
Solution 4
I find all previous answers on-spot but let's put things in context.
The 403 forbidden response comes from the CSRF middleware (see Cross Site Request Forgery protection):
By default, a ‘403 Forbidden’ response is sent to the user if an incoming request fails the checks performed by CsrfViewMiddleware.
Many options are available. I would recommend to follow the answer of @fivef in order to make jQuery add the X-CSRFToken
header before every AJAX request with $.ajaxSetup
.
This answer requires the cookie jQuery plugin. If this is not desirable, another possibility is to add:
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 = jQuery.trim(cookies[i]);
// 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');
BUT: if the setting CSRF_COOKIE_HTTPONLY
is set to True, which often happens as the Security middleware recommends so, then the cookie is not there, even if @ensure_csrf_cookie()
is used. In this case {% csrf_token %}
must be provided in every form, which produces an output such as <input name="csrfmiddlewaretoken" value="cr6O9...FUXf6" type="hidden">
. So the csrfToken
variable would simply be obtained with:
var csrftoken = $('input[name="csrfmiddlewaretoken"]').val();
Again $.ajaxSetup
would be required of course.
Other options which are available but not recommended are to disable the middleware or the csrf protection for the specific form with @csrf_exempt()
.
Solution 5
data: {"csrfmiddlewaretoken" : "{{csrf_token}}"}
You see "403 (FORBIDDEN)", because you don`t send "csrfmiddlewaretoken" parameter. In template each form has this: {% csrf_token %}. You should add "csrfmiddlewaretoken" to your ajax data dictionary. My example is sending "product_code" and "csrfmiddlewaretoken" to app "basket" view "remove":
$(function(){
$('.card-body').on('click',function(){
$.ajax({
type: "post",
url: "{% url 'basket:remove'%}",
data: {"product_code": "07316", "csrfmiddlewaretoken" : "{{csrf_token}}" }
});
})
});
Related videos on Youtube
Annihilator8080
Updated on July 09, 2022Comments
-
Annihilator8080 almost 2 years
I am trying to integrate jquery into a web application I am making with Django framework. I am however having a hard time trying to make a simple
ajax
call to work. My template file that contains the form html and javascript to handle the ajax call looks like:<script type="text/javascript"> $(document).ready(function() { $( "#target" ).submit(function() { console.log('Form was submitted'); $.ajax({ type: "POST", url: "/hello/", // or just url: "/my-url/path/" data: { query: $( "#query" ).val() }, success: function(data) { console.log(data); } }); return false; }); }) </script> <form id="target" action="." method="post">{% csrf_token %} <input id= "query" type="text" value="Hello there"> <input type="submit" value="Search Recent Tweets"> </form>
My
views.py
that is supposed to handle the ajax call looks like:from django.core.context_processors import csrf from django.shortcuts import render_to_response from django.template.loader import get_template from django.template import Context,RequestContext from django.views.decorators.csrf import ensure_csrf_cookie from django.http import HttpResponse # access resource def hello(request): c = {} c.update(csrf(request)) if request.is_ajax(): t = get_template('template.html') #html = t.render(Context({'result': 'hello world'})) con = RequestContext(request, {'result': 'hello world'}) return render_to_response('template.html', c, con) else: return HttpResponse('Not working!')
I have tried to follow the official documentation on Cross-Site Request Forgery Protection and also looked at several stackoverflow questions addressing a similar problem. I have included the
{% csrf_token %}
in myhtml
template file but it still doesn't seem to be working. I get an error in the console suggesting that the ajax call failed:POST http://127.0.0.1:8000/hello/ 403 (FORBIDDEN)
How do I pass the
result
variable along with my http response and get the ajax call to work smoothly? Any help is deeply appreciated.Edit-1
I wasn't supposedly passing the
csrf
token along with my post request. SO as per the documentation I added the following code to my template javascript: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 = jQuery.trim(cookies[i]); // 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'); console.log(csrftoken); //Ajax call function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ crossDomain: false, // obviates need for sameOrigin test beforeSend: function(xhr, settings) { if (!csrfSafeMethod(settings.type)) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } });
When I refresh the template html page in the browser, I get
null
in the console, suggesting that the cookie is not set or not defined. What am I missing? -
Annihilator8080 over 10 yearsI have updated my question as per your suggestion. I still get the same error. I would appreciate if you can tell me how you got it working.
-
Yohn over 10 years"csrfmiddlewaretoken" is a key in your posted data,for example,when you need to ajax login,your posted data may like this: {'username':'username','password':'password','csrfmiddlewaretoken':'CSRF-TOKEN-VALUE'}
-
steinerkelvin over 10 yearsAnd you have the middleware
'django.middleware.csrf.CsrfViewMiddleware'
, in MIDDLEWARE_CLASSES in your settings.py`? -
Annihilator8080 over 10 yearsYes, @kelvinss, I had made the necessary changes in settings.py
-
Annihilator8080 over 10 yearsThanks @PYTY, that was the problem. I wasn't embedding the token.
-
alireza about 9 yearsyour link not work, link changed to this : docs.djangoproject.com/en/1.7/ref/contrib/csrf/#ajax
-
john over 8 yearsi know this has been a while, but does this still hold true even if you've disabled csrf middleware in settings.py?
-
Airith over 7 yearsFinally figured out what was going on through your comment. They should definitely add this to the csrf ajax docs. I had no idea that
CSRF_COOKIE_HTTPONLY
was breaking my ajax posts. -
Borgy Manotoy almost 7 yearsI followed the above code and I can now send ajax() post, but it does not read my data/parameters. Example data: {"name":"John Birada"}. The name parameter is always null. thanks
-
VIISHRUT MAVANII about 5 yearsHi AndrewPt, please consider explaining what exactly you've done, or minimally provide an explanation of what your code does so that people who read the code understand what you're doing exactly. Thanks!
-
AndrewPt about 5 yearsHi, Vishrut Mavani, I`ve added an explanation!
-
Anupam over 4 yearsperfect and straightforward answer
-
Laxmikant over 3 yearscsrf_exempt is not recommended