I'm trying to send $ajax, and I have got it, but I have to send file with my form, in the same or not, doesn't matter. csrf token has not been found and I'm getting error.
My javascript
$(document).ready(function() {
var csrf_token = $('input[name="_token"]').val();
$.ajaxSetup({
headers: {
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
}
});
// $("body").bind("ajaxSend", function(elm, xhr, s) {
// if (s.type == "POST") {
// xhr.setRequestHeader('X-CSRF-Token', csrf_token);
// }
// });
window.getCookie = function(cname) { //window for testing in console
var name = cname + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1);
if (c.indexOf(name) == 0) return c.substring(name.length, c.length);
}
return "";
};
function sendPost() {
var data = $('form').serialize();
var file = $(document.getElementById('files').files[0]);
$.ajax({
type: 'POST',
url: '/delling_data_objects/document/',
//data: $('form').serialize(), it's working
data: file, // its don't
enctype: 'multipart/form-data',
headers: window.getCookie('csrftoken')
});
};
$('#submit').on('click', function() {
sendPost();
});
});
my view.py
def load_files(request):
form = ApartForm(request.POST)
import pdb
pdb.set_trace()
if form.is_valid():
form.save()
file_form = request.POST['file']
for f in file_form:
with open(f) as dest:
for chunk in f.chunks():
dest.write(chunk)
else:
return HttpResponse('form is not valid')
return HttpResponse('ok')
You are not doing it correctly. It feels like you are sending the requestHeader twice.(edit: nevermind didn't see a part of the code was commented)
Based on your code, try something like this :
function sendPost() {
var data = $('form').serialize();
var file = $(document.getElementById('files').files[0]);
var csrftoken = getCookie("csrftoken");
$.ajax({
method: "POST",
url: '/delling_data_objects/document/',
data: data,
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
},
success: function(data) {
// whatever you want to do
}
});
}
$('#submit').on('click', function() {
sendPost();
});
var getCookie = function(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 csrfSafeMethod = function (method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
};
Related
I try to send data with ajax but the format is a string and I need JSON (or formated data)
Data to be sent are displayed in an HTML table.
I loop in all my rows to collect all data to be send using ajax.
But I have an error when I try to make a JSON object when using JSON.Parse(new_parameters).
If use new_parameters in my ajax query, I get False in my ajax view...
If I "stringify" new_parameters to use it in my ajax query, I get data in my ajax view but in string format...
That's mean the way I construct new_parameters is not a good way...
var parameters = {};
var current_parameters = [];
var new_parameters = [];
// Collect data from html data when user click on "Modify settings" button
$(document).on('click', '#modifier', function(event)
{
event.preventDefault();
$('#table_parametrage tr').each(function() {
var parameter = {};
$(this).find('td div').each (function() {
parameter[$(this).attr("col_name")] = $(this).eq(0).html();
});
new_parameters.push(parameter);
});
new_parameters.shift();
// requête ajax > start
// parameters = JSON.parse(new_parameters, null, 2);
console.log(new_parameters);
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');
$.ajax({
type: "POST",
url: $(this).data("ajax-url"),
data: {
csrfmiddlewaretoken: csrftoken,
'data' : new_parameters,
},
dataType: 'json',
success: function (data) {
// alert(data);
},
error : function(resultat, statut, erreur){
//
}
});
// requête ajax > end
// Remise à zéro de la liste
new_parameters = [];
parameters = {};
});
for those interested, even if I am not ure it is the best code, I resolve my problem like this:
JS:
...
parameters = JSON.stringify(new_parameters, null, 2);
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');
$.ajax({
type: "POST",
url: $('#modifier').data("ajax-url"),
data: {
csrfmiddlewaretoken: csrftoken,
'data' : parameters,
},
dataType: 'json',
success: function (data) {
// alert(data);
},
error : function(resultat, statut, erreur){
//
}
});
# requete ajax
def ajax(request):
if request.method == "POST":
data = request.POST.get('data',False)
# https://www.programiz.com/python-programming/json
data_dict = json.loads(data)
print(data_dict)
print(data_dict[0]['ran_st1'])
else:
datas = ''
print('echec')
return render(request, 'randomization_settings/ajax.html', {})
I'm trying to add Ajax like beforeSend function to my XMLHttpRequest. I'm getting following error:
TypeError: Cannot read property 'type' of undefined
Here is my code:
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function beforeSend(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
var http = new XMLHttpRequest();
http.open('POST', messageEndpoint, true);
http.setRequestHeader('Content-type', 'application/json');
http.onreadystatechange = function() {
if (http.readyState === 4 && http.status === 200 && http.responseText) {
Api.setResponsePayload(http.responseText);
}
};
var params = JSON.stringify(payloadToWatson);
if (Object.getOwnPropertyNames(payloadToWatson).length !== 0) {
Api.setRequestPayload(params);
}
// Added beforeSend() function before sending the params
beforeSend();
http.send(params);
I notice your using jQuery... then you can use $ajax method; here an example
$ajax({
url: 'yourURLhere',
data: {some: 'value'},//{} or [] or ""
method: 'POST',
beforeSend: function(jqXHR, settings) {
// do something
},
success: function(data) {
},
error: function(err) {
}
})
Anyone who was in my situation and trying to send csrf token with XMLHttpRequest request. Here is how I solved it:
Create csrf token:
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;
};
Build http request:
var http = new XMLHttpRequest();
http.open('POST', messageEndpoint, true);
http.setRequestHeader('X-CSRFToken', csrfcookie());
function GetViewModelData() {
var RDcViewModel = [];
var recordId = $.trim($("#recordId").val());
for (i = 1; i <= rowCount; i++) {
var item1 = $.trim($("#item1" + i).val()) == '' ? 0 : parseInt($("#item1" + i).val());
var item2 = $.trim($("#item2" + i).val()) == '' ? 0 : parseInt($("#item2" + i).val());
var GrandTotal = (item1 + item2);
var rdtCViewModel = new ItemDetailsViewModel(0, item1, item2, GrandTotal);
RDcViewModel.push(rdtCViewModel);
}
var obj = new ReportViewModel(recordId, RDcViewModel);
var viewmodel = JSON.stringify(obj);
return viewmodel;
}
I have the above sample function that i'm using to iterate over html table rows and storing the row values in an array.
Once i have my array populated, i'm using below code snippet to post the data to my controller.
var PostData = function () {
$(".btnSubmit").click(function () {
var viewmodel = GetViewModelData();
//i want to check from here if viewmodel has any item(row) where GrandTotal is 0 (zero)
$.ajax({
async: true,
cache: false,
contentType: 'application/json; charset=utf-8',
data: viewmodel,
headers: GetRequestVerificationToken(),
type: 'POST',
url: '/' + virtualDirectory + '/Item/DataSave',
success: function (data) {
if (data == true) {
window.location.href = '/' + virtualDirectory + '/Destination/Index';
}
},
error: function (e) {
return false;
}
});
});
}
What i now want to do in my PostData function is to check if my "viewmodel" object contains any item(row) where "GrandTotal" is 0.
using JSON.parse(viewmodel), prepare object of type ReportViewModel with RDcViewModel JS array of type ItemDetailsViewModel and iterate over it to find if any grandtotal == 0 for ItemDetailsViewModel instances
var viewmodel = GetViewModelData(),
var obj = JSON.parse(viewmodel);
var bFoundZero=false;
$.each(obj.RDcViewModelArray, function(idx, elem){
if( elem.GrandTotal === 0 ) bFoundZero=true;
})
if( bFoundZero ) return 0;
As you have stringified it, now you have to parse it back if you want to access its keys and values:
var PostData = function() {
$(".btnSubmit").click(function() {
var viewmodel = GetViewModelData(),
viewObj = JSON.parse(viewmodel),
flag = false; // <-----parse it back here
viewObj.forEach(function(i, el){
flag = el.GrandTotal === 0;
return flag;
});
if(flag){ return false; } // <------ and stop it here.
$.ajax({
async: true,
cache: false,
contentType: 'application/json; charset=utf-8',
data: viewmodel,
headers: GetRequestVerificationToken(),
type: 'POST',
url: '/' + virtualDirectory + '/Item/DataSave',
success: function(data) {
if (data == true) {
window.location.href = '/' + virtualDirectory + '/Destination/Index';
}
},
error: function(e) {
return false;
}
});
});
}
There is no point iterating array again. Break the loop in GetViewModelData() and return false from that function. Then test it in PostData
Inside existing for loop:
var GrandTotal = (item1 + item2);
if(!GrandTotal){
return false;
}
Then in PostData()
var PostData = function () {
$(".btnSubmit").click(function () {
var viewmodel = GetViewModelData();
if(viewmodel === false){
alert('Missing total');
return; //don't proceed
}
/* your ajax */
I am creating an audio player that have 4 dropdown lists each depends on each other to get the right mp3 file, the jquery code works fine until i assign a plugin to the dropdown called (fancyspinbox) to look better.
The problem is the dropdown dont update its value though its triggered successfully.
Kindly find my code below
<script>
$(document).ready(function () {
$('#ddbibletype').fancyspinbox();
$('#ddtestament').fancyspinbox();
$("#booksdd").fancyspinbox();
$("#chapterdd").fancyspinbox();
});
$("#ddtestament").change(function () {
var options = {};
options.url = '#Url.Action("GetBooks", "Home")';
options.type = "POST";
if ($("#ddtestament option:selected").index() == 0)
options.data = JSON.stringify({ testament: 'OT' });
else
options.data = JSON.stringify({ testament: 'NT' });
options.dataType = "json";
options.contentType = "application/json; charset=utf-8";
options.success = function (jsonResult) {
$("#booksdd").empty();
$("#chapterdd").empty();
var jb = $(jsonResult.jbooks);
var jc = $(jsonResult.jchapters);
for (var i = 0; i < jb.length; i++) {
$("#booksdd").append("<option>" + jb[i] + "</option>");
}
for (var i = 0; i < jc.length; i++) {
$("#chapterdd").append("<option>" + jc[i] + "</option>");
}
$("#booksdd").change();
};
options.error = function () { alert("Error retrieving Books!"); };
$.ajax(options);
});
$("#booksdd").change(function () {
var options = {};
options.url = '#Url.Action("GetChapters", "Home")';
options.type = "POST";
if ($("#ddtestament option:selected").index() == 0)
options.data = JSON.stringify({ bookID: $("#booksdd option:selected").index() });
else
options.data = JSON.stringify({ bookID: ($("#booksdd option:selected").index() + 39) });
options.dataType = "json";
options.contentType = "application/json; charset=utf-8";
options.success = function (chapters) {
$("#chapterdd").empty();
for (var i = 0; i < chapters.length ; i++) {
$("#chapterdd").append("<option>" + chapters[i] + "</option>");
}
$("#chapterdd").prop("disabled", false);
$("#chapterdd").change();
};
options.error = function () { alert("Error retrieving chapters!"); };
$.ajax(options);
});
$("#chapterdd").change(function () {
var options = {};
options.url = '#Url.Action("GetTrackPath", "Home")';
options.type = "POST";
if ($("#ddtestament option:selected").index() == 0)
options.data = JSON.stringify({ bibleType: $("#ddbibletype option:selected").index(), bookID: $("#booksdd option:selected").index() + 1, chapterNum: $("#chapterdd option:selected").index() + 1 });
else
options.data = JSON.stringify({ bibleType: $("#ddbibletype option:selected").index(), bookID: ($("#booksdd option:selected").index() + 40), chapterNum: $("#chapterdd option:selected").index() + 1 });
options.dataType = "json";
options.contentType = "application/json; charset=utf-8";
options.success = function (trackpath) {
var audio = $('#bibleplayer');
$('#mpsource').attr('src', trackpath);
audio[0].pause();
audio[0].load();//suspends and restores all audio element
audio[0].oncanplaythrough = audio[0].play();
};
options.error = function () {
alert("Error retrieving Books!");
};
$.ajax(options);
});
I'm assuming you are using this fancyspingbox? https://github.com/mayakokits/jquery.fancyspinbox
There is no mention there of needing to add different event listeners, but they do mention "If you need to access the spinbox element, use the element object.". Possibly that is the solution
ie this line
$("#ddtestament").change(function () {
becomes
$("#ddtestament").element.change(function () {
or
$($("#ddtestament").element).change(function () {
as do the other similar lines.
I have global $.ajaxPrefilter function that filter values for XSS like this:
if (typeof filterXSS == 'function') {
$.ajaxPrefilter(function(options, origOptions, jqXHR) {
if (typeof options.data == 'string') {
var object = {};
options.data.split('&').forEach(function(pair) {
pair = pair.split('=');
object[pair[0]] = decodeURIComponent(pair[1].replace(/\+/g, ' '));
});
var newData = {};
options.data = Object.keys(object).map(function(key) {
var value = filterXSS(object[key]);
return key + '=' + encodeURI(value.replace(/ /g, '+'));
}).join('&');
} else {
console.log(typeof options.data);
console.log(options.data);
}
});
}
it work fine except when I call ajax request with FormData like this:
var file = files.shift();
if (file) {
var formData = new FormData();
formData.append(file);
formData.append('value', '<script>alert("x");</script>');
$.ajax({
method: 'POST',
url: $form.attr('action'),
data: formData,
cache: false,
contentType: false,
processData: false
});
}
how can I process FormData inside $.ajaxPrefilter, I've try to iterate over options.data but only get append:
for (var i in options.data) {
console.log(i);
}