I have below code
function OpenModal()
{
var fname="Quartz";
var mname="Rohit";
var lname="Patel";
var url="{% url 'display_modal' %}"+fname +"/"+mname+"/"+lname;
alert(url);
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById('divcontent').innerHTML=this.responseText;
}
};
xmlhttp.open("GET",url,true);
xmlhttp.send();
}
How to execute the above code on click of a button in django templating language.
url is like
path('member/search/',
views.displayModalView, name="display_modal"),
What ajax does it will prevent a page from reload, this is the magic of ajax. So if you are providing path, this can be use for page reload.
Html:
<script>
function OpenModal(){
var fname="Quartz";
var mname="Rohit";
var lname="Patel";
$.ajax({
type:'POST',
url: "{% url 'display_modal' %}",
data: { csrfmiddlewaretoken: '{{ csrf_token }}'},
success: function(param123){
dict1 = JSON.parse(param123);
let data1 = dict1.test;
alert("Successful call do what ever you want");
alert(data1);
},
error: function(){
alert("sorry");
}
});
}
</script>
urls.py:
what url does it will match the regex with your mentioned url.
the name='display_modal' parameter and the url: "{% url 'display_modal' %}" that you are mentioning in ajax call would be same.
from django.conf.urls import url
urlpatterns = [
url(r'^display_modal', views.displayModalView, name='display_modal')
]
views.py:
import json
from django.http import HttpResponse
def displayModalView(request):
#do what ever you want but at the end return Httpresponse with dictionary if you want
to use dictionary in your ajax call.
param123 = {'test': "Hello_world"}
return HttpResponse(json.dumps(param123))
I think you can use a jQuery Ajax request inside a normal click() method, like descripted here: W3C Documentation
In this case, however, I think you have to declare the url as TemplateAsView, so you can tell Django to immediatly return a template instead of execute a Django view, as described in doc. In the template you can execute the function, as you wish, for example in the template you can insert a call to your function on document ready, and execute when the DOM is loaded, as described here.
To do this you have to change the url, because a view.someView in made to search, inside your view.py, the someView function declaration, but your function is a Javascript so, I presume, you put it inside the template code.
I see that your code is a Javascript function, so I try to figure why you have to call a function like this with Django template system, as a template call, and you can't call the function directly. I think that doing as you want you force a DOM reload everytime and, I think, there are several method to open a modal without a page refresh.
You can add onclick to your button and the value of that should equal to your function
like this
<button onclick='show()' something else ... ></button>
------------------------------ javascript--------------------------------------------------
function show(){
something else ...
}
you can also see jquery documentation
Basically code works as I expected, but my ListView is not refreshing. Everything works fine, but template does not load itself, I must push reload button (all data are loaded correctly then).
I done simple form/input for testing and there is no problem with views. My project requires calendar widget for picking months, and simplest way to do this I found on the internet was Ajax approach.
Ajax function:
$(document).ready(function () {
$(function () {
$("#datetimepicker1").datetimepicker({
viewMode: 'months',
format: 'MM/YYYY',
}).on('dp.change', function (e) {
var url = "/booking/update_months/{{hotel_id}}";
$.ajax({
type: 'GET',
url: url,
dataType: 'json',
data: {
month: e.date.month(),
},
success: function (data) {
},
error: function (data) {
}
});
})
});
});
Url "/booking/update_months/{{hotel_id}}" refers to first View function I'm using for this functionality:
#csrf_exempt
def update_months(request, hotel_id):
if request.GET.get('month'):
month = request.GET.get('month')
request.session['month'] = int(month) + 1
return HttpResponseRedirect(reverse('booking:hotel_statistics', args=(hotel_id,)))
else:
return render_to_response(request, 'booking/hotel_statistics.html')
Then in HotelStatistics ListView I'm doing some stuff in get_context_data function, nothing special here. Just by some "prints" I've tested that the code is being executed until the end of the class.
class HotelStatistics(ListView):
model = Reservation
context_object_name = 'reservations'
template_name = 'booking/hotel_statistics.html'
def get_context_data(self, **kwargs):
.
.
.
return context
I'm pretty sure that I'm missing something with Ajax functionality, It's my first approach to this language. Thanks in advance for your help.
Why are you using AJAX here? Unless I am missing something, you should just have the date picker inside an HTTP GET form that is submitted.
template.html
<!-- The action attribute hardcoded URL value should be replaced with a Django url templatetag. This will allow the url to be resolved based on the router configuration. i.e. {% url "booking:update_months" hotel_id %} -->
<form action="/booking/update_months/{{ hotel_id }}" method="GET">
<input id="date" name="date">
<button type="submit">Update</button>
</form>
<script>
$(document).ready(function() {
$("#date").datetimepicker({
viewMode: 'months',
format: 'yyyy-mm-dd',
});
});
</script>
view.py
#csrf_exempt
def update_months(request, hotel_id):
date = request.GET.get("date")
if date:
request.session["month"] = datetime.strptime(date, "%Y-%m-%d").month
return redirect("booking:hotel_statistics", False, hotel_id)
return render(request, "booking/hotel_statistics.html")
The code above submits an HTTP GET form, resulting in a server side 301 and therefore a "refresh" of your statistics page with the update session data.
Notice, we are sending up the full date information. I am not sure if you are doing this separately, but if you are allowing users to update each date part independent, you could now bring that together into a single update_date function.
I have a Django app that uses React to create a Newsfeed component. When the React Newsfeed component mounts, it makes an ajax call to the Django API to get the current user, and sets the author of a new post to the current user. Below is the code for the new post form React component:
var NewPost = React.createClass({
getInitialState: function() {
return {
author: 'Default Author'
}
},
getUser: function() {
$.ajax({
url: this.props.url + "user/",
dataType: 'json',
method: 'GET',
success: function(data){
this.setState({author: data.fields.first_name});
}.bind(this),
error: function(xhr, status, err) {
console.error("Error with API", status, err.toString());
}.bind(this)
})
},
componentDidMount: function(){
this.getUser();
},
handleSubmit: function(event) {
event.preventDefault();
var author = this.state.author;
var content = React.findDOMNode(this.refs.content).value.trim();
if (!content) {
return;
}
this.props.onPostSubmit({author: author, content: content});
React.findDOMNode(this.refs.content).value = '';
return;
},
render: function() {
return (
<div className="panel panel-default">
<div className="panel-body">
<form onSubmit={this.handleSubmit}>
<div className="form-group">
<textarea className="form-control" ref="content" placeholder="Whats Up" rows="3" id="newpost-input" />
<br/>
<input type="submit" className="btn btn-primary" id='newpost-submit' value="Submit" />
</div>
</form>
</div>
</div>
)
}
});
When I test this code manually everything works the way it should. I login, make a post, and my name is displayed as the author of the post. But when I test this using Selenium, the author is 'Default Author'; it is not getting changed. In my Selenium test I login to my app with my login credentials, and everything works as it should, except that the author of the post is not being changed from 'Default Author' to my name.
At first I thought that Selenium was doing its work before the ajax call had time to finish. So I added some wait times to my Selenium tests but the author name never gets changed. Any ideas why the ajax call seems to not be working?
UPDATE
Here is the relevant Selenium code:
class FunctionalTest(LiveServerTestCase):
def login(self):
self.browser.find_element_by_id('username').send_keys(LOGIN['USERNAME'])
self.browser.find_element_by_id('password').send_keys(LOGIN['PASSWORD'] + '\n')
def create_post(self, content=""):
self.browser.find_element_by_id('newpost-input').send_keys(content)
self.browser.find_element_by_id('newpost-submit').click()
def test_correct_author_name_is_displayed(self):
self.login()
self.create_post('A Post')
self.assertIn("Jonathan", self.browser.find_element_by_id('newsfeed').text)
I know the login with my credentials is successful because I added {{user}} to my django template, and added a print statement to the selenium test to print the text of the body and {{user}} is correctly displayed as my username.
Another test I did was to see if the react function componentDidMount was being called. In the componentDidMount function I did this:
componentDidMount: function() {
console.log("component mounting");
this.getUser();
console.log("component mounted");
},
In addition to that I also added console.logs to the success and error functions of the getUser ajax call. The console.logs from the componentDidMount function work, but the console.logs inside the ajax call do not.
I could use some help complying with Django's CSRF protection mechanism via my AJAX post. I've followed the directions here:
http://docs.djangoproject.com/en/dev/ref/contrib/csrf/
I've copied the AJAX sample code they have on that page exactly:
http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax
I put an alert printing the contents of getCookie('csrftoken') before the xhr.setRequestHeader call and it is indeed populated with some data. I'm not sure how to verify that the token is correct, but I'm encouraged that it's finding and sending something.
But Django is still rejecting my AJAX post.
Here's my JavaScript:
$.post("/memorize/", data, function (result) {
if (result != "failure") {
get_random_card();
}
else {
alert("Failed to save card data.");
}
});
Here's the error I'm seeing from Django:
[23/Feb/2011 22:08:29] "POST /memorize/ HTTP/1.1" 403 2332
I'm sure I'm missing something, and maybe it's simple, but I don't know what it is. I've searched around SO and saw some information about turning off the CSRF check for my view via the csrf_exempt decorator, but I find that unappealing. I've tried that out and it works, but I'd rather get my POST to work the way Django was designed to expect it, if possible.
Just in case it's helpful, here's the gist of what my view is doing:
def myview(request):
profile = request.user.profile
if request.method == 'POST':
"""
Process the post...
"""
return HttpResponseRedirect('/memorize/')
else: # request.method == 'GET'
ajax = request.GET.has_key('ajax')
"""
Some irrelevent code...
"""
if ajax:
response = HttpResponse()
profile.get_stack_json(response)
return response
else:
"""
Get data to send along with the content of the page.
"""
return render_to_response('memorize/memorize.html',
""" My data """
context_instance=RequestContext(request))
Thanks for your replies!
If you use the $.ajax function, you can simply add the csrf token in the data body:
$.ajax({
data: {
somedata: 'somedata',
moredata: 'moredata',
csrfmiddlewaretoken: '{{ csrf_token }}'
},
Real solution
Ok, I managed to trace the problem down. It lies in the Javascript (as I suggested below) code.
What you need is this:
$.ajaxSetup({
beforeSend: function(xhr, settings) {
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;
}
if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
// Only send the token to relative URLs i.e. locally.
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
}
});
instead of the code posted in the official docs:
https://docs.djangoproject.com/en/2.2/ref/csrf/
The working code, comes from this Django entry: http://www.djangoproject.com/weblog/2011/feb/08/security/
So the general solution is: "use ajaxSetup handler instead of ajaxSend handler". I don't know why it works. But it works for me :)
Previous post (without answer)
I'm experiencing the same problem actually.
It occurs after updating to Django 1.2.5 - there were no errors with AJAX POST requests in Django 1.2.4 (AJAX wasn't protected in any way, but it worked just fine).
Just like OP, I have tried the JavaScript snippet posted in Django documentation. I'm using jQuery 1.5. I'm also using the "django.middleware.csrf.CsrfViewMiddleware" middleware.
I tried to follow the the middleware code and I know that it fails on this:
request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')
and then
if request_csrf_token != csrf_token:
return self._reject(request, REASON_BAD_TOKEN)
this "if" is true, because "request_csrf_token" is empty.
Basically it means that the header is NOT set. So is there anything wrong with this JS line:
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
?
I hope that provided details will help us in resolving the issue :)
Add this line to your jQuery code:
$.ajaxSetup({
data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
});
and done.
The issue is because django is expecting the value from the cookie to be passed back as part of the form data. The code from the previous answer is getting javascript to hunt out the cookie value and put it into the form data. Thats a lovely way of doing it from a technical point of view, but it does look a bit verbose.
In the past, I have done it more simply by getting the javascript to put the token value into the post data.
If you use {% csrf_token %} in your template, you will get a hidden form field emitted that carries the value. But, if you use {{ csrf_token }} you will just get the bare value of the token, so you can use this in javascript like this....
csrf_token = "{{ csrf_token }}";
Then you can include that, with the required key name in the hash you then submit as the data to the ajax call.
The {% csrf_token %} put in html templates inside <form></form>
translates to something like:
<input type='hidden' name='csrfmiddlewaretoken' value='Sdgrw2HfynbFgPcZ5sjaoAI5zsMZ4wZR' />
so why not just grep it in your JS like this:
token = $("#change_password-form").find('input[name=csrfmiddlewaretoken]').val()
and then pass it e.g doing some POST, like:
$.post( "/panel/change_password/", {foo: bar, csrfmiddlewaretoken: token}, function(data){
console.log(data);
});
Non-jquery answer:
var csrfcookie = function() {
var cookieValue = null,
name = 'csrftoken';
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
};
usage:
var request = new XMLHttpRequest();
request.open('POST', url, true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.setRequestHeader('X-CSRFToken', csrfcookie());
request.onload = callback;
request.send(data);
It seems nobody has mentioned how to do this in pure JS using the X-CSRFToken header and {{ csrf_token }}, so here's a simple solution where you don't need to search through the cookies or the DOM:
var xhttp = new XMLHttpRequest();
xhttp.open("POST", url, true);
xhttp.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
xhttp.send();
If your form posts correctly in Django without JS, you should be able to progressively enhance it with ajax without any hacking or messy passing of the csrf token. Just serialize the whole form and that will automatically pick up all your form fields including the hidden csrf field:
$('#myForm').submit(function(){
var action = $(this).attr('action');
var that = $(this);
$.ajax({
url: action,
type: 'POST',
data: that.serialize()
,success: function(data){
console.log('Success!');
}
});
return false;
});
I've tested this with Django 1.3+ and jQuery 1.5+. Obviously this will work for any HTML form, not just Django apps.
The accepted answer is most likely a red herring. The difference between Django 1.2.4 and 1.2.5 was the requirement for a CSRF token for AJAX requests.
I came across this problem on Django 1.3 and it was caused by the CSRF cookie not being set in the first place. Django will not set the cookie unless it has to. So an exclusively or heavily ajax site running on Django 1.2.4 would potentially never have sent a token to the client and then the upgrade requiring the token would cause the 403 errors.
The ideal fix is here:
http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#page-uses-ajax-without-any-html-form
but you'd have to wait for 1.4 unless this is just documentation catching up with the code
Edit
Note also that the later Django docs note a bug in jQuery 1.5 so ensure you are using 1.5.1 or later with the Django suggested code:
https://docs.djangoproject.com/en/dev/ref/csrf/#ajax
Use Firefox with Firebug. Open the 'Console' tab while firing the ajax request. With DEBUG=True you get the nice django error page as response and you can even see the rendered html of the ajax response in the console tab.
Then you will know what the error is.
As it is not stated anywhere in the current answers, 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 in your js file:
$.ajax({
type: 'POST',
url: somepathname + "do_it/",
data: {csrfmiddlewaretoken: window.CSRF_TOKEN},
success: function() {
console.log("Success!");
}
})
I've just encountered a bit different but similar situation. Not 100% sure if it'd be a resolution to your case, but I resolved the issue for Django 1.3 by setting a POST parameter 'csrfmiddlewaretoken' with the proper cookie value string which is usually returned within the form of your home HTML by Django's template system with '{% csrf_token %}' tag. I did not try on the older Django, just happened and resolved on Django1.3.
My problem was that the first request submitted via Ajax from a form was successfully done but the second attempt from the exact same from failed, resulted in 403 state even though the header 'X-CSRFToken' is correctly placed with the CSRF token value as well as in the case of the first attempt.
Hope this helps.
Regards,
Hiro
You can paste this js into your html file, remember put it before other js function
<script>
// using jQuery
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;
}
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$(document).ready(function() {
var csrftoken = getCookie('csrftoken');
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
});
</script>
Easy ajax calls with Django
(26.10.2020)
This is in my opinion much cleaner and simpler than the correct answer.
The view
#login_required
def some_view(request):
"""Returns a json response to an ajax call. (request.user is available in view)"""
# Fetch the attributes from the request body
data_attribute = request.GET.get('some_attribute') # Make sure to use POST/GET correctly
# DO SOMETHING...
return JsonResponse(data={}, status=200)
urls.py
urlpatterns = [
path('some-view-does-something/', views.some_view, name='doing-something'),
]
The ajax call
The ajax call is quite simple, but is sufficient for most cases. You can fetch some values and put them in the data object, then in the view depicted above you can fetch their values again via their names.
You can find the csrftoken function in django's documentation. Basically just copy it and make sure it is rendered before your ajax call so that the csrftoken variable is defined.
$.ajax({
url: "{% url 'doing-something' %}",
headers: {'X-CSRFToken': csrftoken},
data: {'some_attribute': some_value},
type: "GET",
dataType: 'json',
success: function (data) {
if (data) {
console.log(data);
// call function to do something with data
process_data_function(data);
}
}
});
Add HTML to current page with ajax
This might be a bit off topic but I have rarely seen this used and it is a great way to minimize window relocations as well as manual html string creation in javascript.
This is very similar to the one above but this time we are rendering html from the response without reloading the current window.
If you intended to render some kind of html from the data you would receive as a response to the ajax call, it might be easier to send a HttpResponse back from the view instead of a JsonResponse. That allows you to create html easily which can then be inserted into an element.
The view
# The login required part is of course optional
#login_required
def create_some_html(request):
"""In this particular example we are filtering some model by a constraint sent in by
ajax and creating html to send back for those models who match the search"""
# Fetch the attributes from the request body (sent in ajax data)
search_input = request.GET.get('search_input')
# Get some data that we want to render to the template
if search_input:
data = MyModel.objects.filter(name__contains=search_input) # Example
else:
data = []
# Creating an html string using template and some data
html_response = render_to_string('path/to/creation_template.html', context = {'models': data})
return HttpResponse(html_response, status=200)
The html creation template for view
creation_template.html
{% for model in models %}
<li class="xyz">{{ model.name }}</li>
{% endfor %}
urls.py
urlpatterns = [
path('get-html/', views.create_some_html, name='get-html'),
]
The main template and ajax call
This is the template where we want to add the data to. In this example in particular we have a search input and a button that sends the search input's value to the view. The view then sends a HttpResponse back displaying data matching the search that we can render inside an element.
{% extends 'base.html' %}
{% load static %}
{% block content %}
<input id="search-input" placeholder="Type something..." value="">
<button id="add-html-button" class="btn btn-primary">Add Html</button>
<ul id="add-html-here">
<!-- This is where we want to render new html -->
</ul>
{% end block %}
{% block extra_js %}
<script>
// When button is pressed fetch inner html of ul
$("#add-html-button").on('click', function (e){
e.preventDefault();
let search_input = $('#search-input').val();
let target_element = $('#add-html-here');
$.ajax({
url: "{% url 'get-html' %}",
headers: {'X-CSRFToken': csrftoken},
data: {'search_input': search_input},
type: "GET",
dataType: 'html',
success: function (data) {
if (data) {
/* You could also use json here to get multiple html to
render in different places */
console.log(data);
// Add the http response to element
target_element.html(data);
}
}
});
})
</script>
{% endblock %}
Update 2022
In a CSRF attack, an innocent end user is tricked by an attacker into submitting a web request that they did not intend
option 1
from django.views.decorators.csrf import csrf_exempt
from django.http.response import JsonResponse
#csrf_exempt
def commentDeletePost(request):
if request.is_ajax() and request.method == 'POST':
try:
comment = Comment.objects.get(pk=request.POST['pk'])
if comment.author != request.user:
return JsonResponse({'e': 'Forbidden'}, status=403)
comment.delete()
return JsonResponse({}, status=200)
execpt Comment.DoesNotExist:
return JsonResponse({'e': 'Not Found'}, status=404)
option 2
<div id="csrf">
{% csrf_token %}
</div>
<script type="text/javascript">
window.crud = {
commentDelete: function(
pk,
success,
error,
){
$.ajax({
headers: {'X-CSRFToken': document.getElementById('csrf').querySelector('input').value},
type: "POST",
url: "{% url 'comment-delete-post' %}",
data: {
pk: pk,
},
success: success,
error: error,
})
},
}
</script>
two options have its own advantage. First option will discard csrf token, which will not protecte your site from csrf attacks, but it will allow user to send more than one request with same Ajax function.
the second option will restrict user to send one Ajax request only since csrf token can only be used once, but it is more secure. I personally prefer option 1, since Ajax functions such as like, star, unlike requires more than one Ajax call, and it is not a risky function to allow user call more than once.
In my case the problem was with the nginx config that I've copied from main server to a temporary one with disabling https that is not needed on the second one in the process.
I had to comment out these two lines in the config to make it work again:
# uwsgi_param UWSGI_SCHEME https;
# uwsgi_pass_header X_FORWARDED_PROTO;
One CSRF token is assigned to every session ( i.e. every time you log in).
So before you wish to get some data entered by user and send that as ajax call to some function which is protected by csrf_protect decorator, try to find the functions that are being called before you are getting this data from user. E.g. some template must be being rendered on which your user is entering data.
That template is being rendered by some function.
In this function you can get csrf token as follows:
csrf = request.COOKIES['csrftoken']
Now pass this csrf value in context dictionary against which template in question is being rendered.
Now in that template write this line:
Now in your javascript function, before making ajax request, write this:
var csrf = $('#csrf').val() this will pick value of token passed to template and store it in variable csrf.
Now while making ajax call, in your post data, pass this value as well :
"csrfmiddlewaretoken": csrf
This will work even if you are not implementing django forms.
In fact, logic over here is : You need token which you can get from request.
So you just need to figure out the function being called immediately after log in. Once you have this token, either make another ajax call to get it or pass it to some template which is accessible by your ajax.
for someone who comes across this and is trying to debug:
1) the django csrf check (assuming you're sending one) is here
2) In my case, settings.CSRF_HEADER_NAME was set to 'HTTP_X_CSRFTOKEN' and my AJAX call was sending a header named 'HTTP_X_CSRF_TOKEN' so stuff wasn't working. I could either change it in the AJAX call, or django setting.
3) If you opt to change it server-side, find your install location of django and throw a breakpoint in the csrf middleware.f you're using virtualenv, it'll be something like: ~/.envs/my-project/lib/python2.7/site-packages/django/middleware/csrf.py
import ipdb; ipdb.set_trace() # breakpoint!!
if request_csrf_token == "":
# Fall back to X-CSRFToken, to make things easier for AJAX,
# and possible for PUT/DELETE.
request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '')
Then, make sure the csrf token is correctly sourced from request.META
4) If you need to change your header, etc - change that variable in your settings file
If someone is strugling with axios to make this work this helped me:
import axios from 'axios';
axios.defaults.xsrfCookieName = 'csrftoken'
axios.defaults.xsrfHeaderName = 'X-CSRFToken'
Source: https://cbuelter.wordpress.com/2017/04/10/django-csrf-with-axios/
Here's a less verbose solution provided by Django:
<script type="text/javascript">
// using jQuery
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
// set csrf header
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
// Ajax call here
$.ajax({
url:"{% url 'members:saveAccount' %}",
data: fd,
processData: false,
contentType: false,
type: 'POST',
success: function(data) {
alert(data);
}
});
</script>
Source: https://docs.djangoproject.com/en/1.11/ref/csrf/
Using Django 3.1.1 and all solutions I tried failed. However, adding the "csrfmiddlewaretoken" key to my POST body worked. Here's the call I made:
$.post(url, {
csrfmiddlewaretoken: window.CSRF_TOKEN,
method: "POST",
data: JSON.stringify(data),
dataType: 'JSON',
});
And in the HTML template:
<script type="text/javascript">
window.CSRF_TOKEN = "{{ csrf_token }}";
</script>
Related to the chosen Answer, just want to add on to the chosen Answer.
In that answer, regarding the solution with .ajaxSetup(...). In your Django settings.py, if you have
CSRF_USE_SESSIONS = True
It would cause the chosen Answer to not work at all. Deleting that line, or setting it to False worked for me while implementing the chosen Answer's solution.
Interestingly, if you set the following in your Django settings.py
CSRF_COOKIE_HTTPONLY = True
This variable will not cause the chosen Answer's solution to stop functioning.
Both CSRF_USE_SESSIONS and CSRF_COOKIE_HTTPONLY comes from this official Django doc https://docs.djangoproject.com/en/2.2/ref/csrf/
(I do not have enough rep to comment, so I am posting my inputs an Answer)
I have a solution. in my JS I have two functions.
First to get Cookies (ie. csrftoken):
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const 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;
}
Second one is my ajax function. in this case it's for login and in fact doesn't return any thing, just pass values to set a session:
function LoginAjax() {
//get scrftoken:
const csrftoken = getCookie('csrftoken');
var req = new XMLHttpRequest();
var userName = document.getElementById("Login-Username");
var password = document.getElementById("Login-Password");
req.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
//read response loggedIn JSON show me if user logged in or not
var respond = JSON.parse(this.responseText);
alert(respond.loggedIn);
}
}
req.open("POST", "login", true);
//following header set scrftoken to resolve problem
req.setRequestHeader('X-CSRFToken', csrftoken);
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
req.send("UserName=" + userName.value + "&Password=" + password.value);
}