django/ajax: Unable to get Ajax post data in the views.py - ajax

I had a problem getting ajax post data from django backend, I don't know how to pass the value, please help.
In html I have simply this:
<form id="get_vulns_from_family">
<label for="family_content">Enter a family name to display the NVTs</label>
<input id="family_content" />
<input type="submit" value="search" />
</form>
In javascript I wrote this:
$(function() {
$("#get_vulns_from_family").submit(function(event) {
var family_text = $("#family_content").val();
var family_data = {"family": family_text};
$.ajax({
url: "/template_conf/get_vulns_from_family",
type: "POST",
data: family_data,
success: function(response) {
console.log(response);
},
error: function(response) {
console.log("failed!");
}
});
// prevent default posting of form
event.preventDefault();
});
});
In Django method corresponding to url /template_conf/get_vulns_from_family, I tried this:
def get_vuln_from_family(request):
family = request.POST['family']
# some other operations to get value for variable "json_data"
return HttpResponse(simplejson.dumps(json_data))
But django said: MultiValueDictKeyError: "Key 'family' not found in <QueryDict: {}>", which means the POST dictionary is empty.
Am I using the wrong way to get post data? If so what should I do? Thanks.

your url "/template_conf/get_vulns_from_family" is missing a trailing slash. django will typically redirect this to "/template_conf/get_vulns_from_family/", dropping the POST data

If your CSRF enabled then simple ajax post do not work. you will have to add the csrf token and set it to the ajax request header.
For Ajax POST request, you have to pass the CSRF token in as POST data with every POST request. For this reason, you must get CSRF token first. Since you have enabled CSRF protection so you will get the token from csrftoken cookie. The CSRF token cookie is named csrftoken by default. Acquiring the token is very straight forward and it can be achieved using the below code snippet.
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]);
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function csrfSafeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function sameOrigin(url) {
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
!(/^(\/\/|http:|https:).*/.test(url));
}
$(function() {
$("#person_form_id").submit(function(event){
event.preventDefault();
$.ajax({
type:$(this).attr('method'),
url:"",
data:$(this).serialize(),
success: function(){
$('#message').html("<h2 style='color:green;'>Person Form Submitted!</h2>")
},
error: function(){
$('#message').html("<h2 style='color:red;'>Can't submit form</h2>")
}
});
return false;
});
});
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
// Send the token to same-origin, relative URLs only.
// Send the token only if the method warrants CSRF protection
// Using the CSRFToken value acquired earlier
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});

Related

Django: How to send csrf_token with Ajax

I have my Ajax in a jQuery function:
btnApplyConfig.js:
$(".btnApplyConfig").click(function(){
var token = $("input[name=csrfmiddlewaretoken]").val();
// Some other vars I'm sending properly
console.log('token: '+token); //printing correctly
$("#"+frm).submit(function(e){
e.preventDefault();
console.log('Post method via ajax');
$.ajax({
url: '/ajax/validate_config',
type: 'POST',
data: {
'token': token,
//and other stuff I'm sending properly
},
dataType: 'json',
});
});
});
my Django view:
def validate_config(request):
token = request.GET.get('token', None)
#some other vars I've sent ok with ajax
data = {
#some vars
'token': token,
}
if request.method == 'POST':
item = MyClass.objects.filter(my_keyword=my_filter_values).update(my_ajax_values)
return JsonResponse(data)
All the data is being processed properly, the only problem for me is that I'm getting the following error:
Forbidden (CSRF token missing or incorrect.): /ajax/validate_config/
I've put some prints in view in order to check if vars are being sent properly, and yes they are.
How could I handle it?
I checked some tutorials but I couldn't find a solution so far.
A very simpler way
let cookie = document.cookie
let csrfToken = cookie.substring(cookie.indexOf('=') + 1)
$.ajax({
url: 'url/path',
type: 'POST',
headers: {
'X-CSRFToken': csrfToken
}
})
You can use this. You don't have to put anything in your view for it. It will automatically find it.
$.ajax({
url: ,
type: "POST",
data: {
'csrfmiddlewaretoken': $("input[name=csrfmiddlewaretoken]").val()
// plus other data
},
dataType: 'json',
success: ,
});
You probably also want to add if request.is_ajax() to your view.
This was the solution that worked for me in this case:
Added this code before the Ajax code:
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');
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);
}
}
});

Send file to Django througth Ajax

I was working with data just POSTing or GETting through AJAX until a file wanted to cause some problems :P
AJAX dosnt work if I have processData and contentType set to true. But if I set processData and contentType set to false, I got an CSRF TOKEN MISSING error.
How can I send the code with 'csrfmiddlewaretoken' and be able to manage the file too.
this is my jQuery code:
$(document).ready(function(){
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');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function sameOrigin(url) {
// test that a given url is a same-origin URL
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
// Send the token to same-origin, relative URLs only.
// Send the token only if the method warrants CSRF protection
// Using the CSRFToken value acquired earlier
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
$('.guardar-cambios-pedido').click(function(){
var url = $(this).data('url');
// Obtiene los datos de los inputs
if ($("#editarPedidoModal .checkAnuladoPedido").is(":checked")){
var anulado = true;
} else {
var anulado = false;
}
var codigo = $('.inputCodigoPedido').val();
var usuario = $('.inputUsuarioPedido').val();
var estado = $('.selectEstadoPedido').val();
var factura = $('.inputFacturaPedido').prop('files')[0];
// Crea un objeto datos
datos = {
'codigo': codigo,
'usuario': usuario,
'estado': estado,
'factura': factura,
'anulado': anulado,
}
// Envia los datos e los inputs al servidor
$.ajax({
type: 'POST',
url: url,
data: {'datos': datos},
processData: false,
//contentType: false,
//dataType: "multipart/form-data",
success: function(contenido){
//things done if success
}
});
. . . more code . . .
in my views.py
I'm trying to receive my data in this way:
if req.POST:
normal_data = req.POST.get('datos[key]', '')
file_data = req.FILES.get('datos[factura]', '')
UPDATE 1: I've updated my code and now the CSRF problem is gone.. What I have now is that i can't access data from the view.
AJAX call returns success, but no data even trying with datos['key'] or name of input.
Am I missing the way of "sending data"?
Finally, I found the solution by doing the following:
Added malsup jQuery form plugin: http://malsup.com/jquery/form/#getting-started
<script src="http://malsup.github.com/jquery.form.js"></script>
on my JS, I've setted the options and submited the form via ajaxSubmit()
$("#btn-submit").click(function(){
options = {
url: $('#form').prop('action'),
type: 'POST',
success: function(response) {
alert('Done');
}
};
$('#form').ajaxSubmit(options)
})
On my django views I get my data like any other POST request.
def some_view(request):
if request.POST:
other_inputs = request.POST.get('input_name', '')
file_input = request.FILES.get('input_name', '')
... more code ...
CSRF TOKEN on Header:
$(document).ready(function(){
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');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function sameOrigin(url) {
// test that a given url is a same-origin URL
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
// Send the token to same-origin, relative URLs only.
// Send the token only if the method warrants CSRF protection
// Using the CSRFToken value acquired earlier
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
}); // Ends document.ready
Cya!

Django Ajax Request still results to CSRF Token Missing or Incorrect

I tried all the documentation on Django and other answers here in StackOverflow but the result is still (CSRF Token Missing or Incorrect)
So here is my view in views.py:
class MyView(View):
#method_decorator(ensure_csrf_cookie)
def post(self, request, *args, **kwargs):
t = TemplateResponse(request, 'mytemplate.html', data)
t.render()
return JsonResponse({'html' : t.content, 'title' : data['title']})
and this is the ajax in my js file which is in a function for a click event:
$.ajax({
url: window.location.href,
type: 'POST',
data: data,
beforeSend:
function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
var token = $.cookie('csrftoken');
console.log(token);
xhr.setRequestHeader("X-CSRFToken", token);
}
},
success:
function(result) {
},
});
The first call is successful but the succeeding call leads to missing token.
For the debugging, I used console.log and it is returning a different token every click.
Add the below code in the script. This will send the csrf token in the request in each ajax request
1. This will allow to get csrf token
// 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;
}
var csrftoken = getCookie('csrftoken');
2. This will send csrf token on every ajax request
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);
}
}
});
3.Now send your ajax request
$.ajax({
url: window.location.href,
type: 'POST',
data: data,
success: function(result) {
console.log(result);
},
});
For more information visit django official documentation

How to return new csrf token at ajax POST in Django?

I have this simple Like button that works well when used with #csrf_exempt:
Template
<p id="like_count"> {{ topic.likes }}</p>
<span data-type="topic" title="Like"> {% csrf_token %}
<i class="fa fa-thumbs-up" id="liket" name="{{topic.id}}">
Ajax
$(function(){
$('#liket').click(function(){
$.ajax({
type: "POST",
url: "/like/",
data: {
'topic_id': $(this).attr('name'),
'csrfmiddlewaretoken': '{{csrf_token}}'
},
success: tlikeSuccess,
dataType: 'html'
});
});
});
function tlikeSuccess(data, textStatus, jqXHR)
{
$('#like_count').html(data);
}
and views:
##csrf_exempt
def topic_like(request):
args = {}
if request.method == 'POST':
user = request.POST.get('user')
lu= request.user #User.objects.get(username= user)
topic_id = int(request.POST.get('topic_id'))
try:
liked_topic = Topic.objects.get(id = topic_id)
except:
liked_topic = None
if TopicLike.objects.filter(liker=request.user.id, topic=topic_id).exists():
liked_topic.likes -=1
liked_topic.save()
TopicLike.objects.filter(topic=topic_id, liker=request.user.id).delete()
else:
liked_topic.likes +=1
liked_topic.save()
newliker = TopicLike(topic=topic_id, liker=request.user.id)
newliker.save()
#args.update(csrf(request))
args['likes'] = str(liked_topic.likes)
return render(request, 'ajax_like.html', args)
However I don't like this workaround that ignores the CSRF, as it could be vulnerable.
On the other hand, I could not manage to return a new CSRF token to the template so I appreciate your hints to integrate CSRF into this button.
Django in its docs has defined to actually set the header on AJAX request, while protecting the CSRF token from being sent to other domains using settings.crossDomain in jQuery 1.5.1 and newer.
Acquiring the token:
// 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;
}
var csrftoken = getCookie('csrftoken');
Setting the CSRFToken in the header:
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);
}
}
});
Also try this method to embed CSRF token in each AJAX request given on this SO link.
$(function () {
$.ajaxSetup({
headers: { "X-CSRFToken": getCookie("csrftoken") }
});
});
you can add the csrf token manually, using javascript.
https://docs.djangoproject.com/en/1.8/ref/csrf/#ajax

Django CSRF failing with ajax

I have a problem with using Django CSRF with Ajax. I get a 403 Forbidden. I have done all the CSRF things that I normally do with a non-ajax request, but I still have this problem. I'm thinking this has something to do with the javascript snippet at https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax.
$(document).ajaxSend(function(event, 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;
}
function sameOrigin(url)
{
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
function safeMethod(method)
{
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
if (!safeMethod(settings.type) && sameOrigin(settings.url))
{
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
});
I'm not currently using this snippet, mostly because I don't understand a word of it and I don't know how to incorporate it into my jquery ajax call:
function submit_search()
{
$.ajax({
data: {query: document.search_form.query.value},
datatype: 'json',
success: function(data, textStatus, XMLHttpRequest)
{
if (data)
{
if (check_authentication(data))
{
$("#results").html("");
var results = data[0];
var length = data[1];
for (var index = 0; index < results.length; ++index)
{
var result = results[index];
$("#results").append("<p><a href='/entities/" + result["id"] + "'>" + result["name"] +
"</a><br />" + result["description"] + "</p>");
}
}
else
{
offer_login();
}
}
},
type: 'POST',
url: '/ajax/search',
});
}
Does anyone know how I should go about adding this snippet to my code?
Also tried:
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
// Only send the token to relative URLs i.e. locally.
xhr.setRequestHeader("X-CSRFToken",
$("#csrfmiddlewaretoken").val());
}
}
});
but this also does not seem to work, although I'm not sure whether I should be doing something for the bit about #csrfmiddlewaretoken in my form
Thanks
All you need to do is paste the code block in such a way that the code in it runs. If you have a global JS file, you should be able to just add that JavaScript to the end of said file, and it will fix the problem.
well, couple steps required as stated in https://docs.djangoproject.com/en/dev/ref/contrib/csrf/
To summarize the tedious django doc, you will need to:
1. install jquery.cookie plugins
2. make sure crsf_token is passing around
for example, in your template, the form must contain the following hidden field
<input type="hidden" name="csrfmiddlewaretoken" value="{{csrf_token}}"/>
In your ajax request, you should so similar things like
csrf_token = $.cookie('csrftoken');
$.ajax({
url: '/url/',
type: 'POST',
beforeSend: function(xhr, settings) {
xhr.setRequestHeader("X-CSRFToken", csrf_token);
},
data: $('.form').serialize(), //assume you are submit a form
}).done(function(response){
console.log(response)
});
one small tricks that you might be missing is, your landing page(non-ajax) will need #csrf_protect decorator to set up cookie, if you don't do that, the cookie won't exists and the method will fail. If you don't want to do #csrf_protect decorator, you can always refer back to the doc and specifically setup the cookie. Either way will work.
Hope this helps.

Resources