I'm using ajax to pass data to a view for save in database.
In javascript the data look correct but in the view is null.
Read the comments in code for other questions and informations
My javascript:
...
var changed_element=[];
var changed_value=[];
document.getElementById('tabella').addEventListener('change', function(event){
...
changed_element.push(element); //list of list of string
changed_value.push(elem[elem.value].text); //list of string
...
});
document.getElementById('btn-save').addEventListener('click', function() {
console.log('changed_element', changed_element) //print the right value
$.ajax({type: 'POST',
url: '/salva-conoscenze-rapporti/',
data: {
changed_element: changed_element,
changed_value: changed_value //<= comma?
},
success: function(msg) {
console.log(msg) //prints 'It works'
document.getElementById('btn-save').style.display = 'none';
} //<= comma?
});
});
My view:
#staff_member_required
#ensure_csrf_cookie #I need this?
def salva_conoscenze_rapporti(request):
if request.is_ajax():
changed_element = request.POST.get('changed_element', None)
changed_value = request.POST.get('changed_value', None)
msg='it works'
print(changed_element) #prints None instead of array
print(changed_value)
else:
msg="it doesn't work"
return HttpResponse(msg)
My template base.html:
...
<script>
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);
}
}
});
</script>
...
My template:
{% extends 'base.html' %}
...
Basically print(changed_element) should gives the data instead gives None.
My MIDDLEWARE_CLASSES in settings.py:
MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
My variables:
changed_element=[ [ "conoscenza", "Cliente1", "Cliente2" ] ];
changed_value=[ "Generale" ];
console.log(changed_element) gives: Array [ Array[3] ]
To get the cookie you also can use with 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');
And then, I'll correcting your script.
// $('.btn-save').click(function() { // to simply with jquery
document.getElementById('btn-save').addEventListener('click', function() {
$.ajax({
type: 'POST',
url: '/salva-conoscenze-rapporti/',
data: {
"changed_element" : changed_element,
"changed_value" : changed_value,
"csrfmiddlewaretoken": csrftoken // from `var csrftoken;`
},
success: function(msg) {
console.log(msg) //prints 'It works'
document.getElementById('btn-save').style.display = 'none';
} //<= comma?
});
});
Or like this one:
$('.btn-save').click(function() {
var form = new FormData();
form.append('changed_element', changed_element);
form.append('changed_value', changed_value);
form.append('csrfmiddlewaretoken', getCookie('csrftoken'));
$.ajax({
type: 'POST',
url: '/salva-conoscenze-rapporti/',
data: form,
processData: false,
contentType: false,
success: function(msg) {
console.log(msg) //prints 'It works'
document.getElementById('btn-save').style.display = 'none';
}
});
});
In your views.py
from django.views.decorators.csrf import csrf_protect
#csrf_protect
#staff_member_required
def salva_conoscenze_rapporti(request):
if request.method == 'POST' and request.is_ajax():
changed_element = request.POST.get('changed_element', None)
changed_value = request.POST.get('changed_value', None)
msg = 'it works'
print(changed_element)
print(changed_value)
else:
msg="it doesn't work"
return HttpResponse(msg)
Hope it can help.
Related
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);
}
}
});
There is a update view api made to update the content of employee. I can update from the django rest framework view.
I'm using jquery ajax to update but its not working.
$(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));
}
$(".update-employee").submit(function(event){
event.preventDefault()
var this_ = $(this)
var form = this_.serializeArray()
$.each(form, function(key, value){
})
var formData = this_.serialize()
console.log(formData);
var temp =
{
"name": form[4].value,
"email": form[1].value,
"address": form[2].value,
"phone_number": form[3].value,
"username": {{ user_id }},
"school": {{ school_id}},
"language_id": {{ language_id }}
}
$.ajax({
url: "/api/student/{{ id }}",
data: JSON.stringify(temp),
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
},
method: "PUT",
contentType: "application/json; charset=utf-8",
dataType: 'json',
success: function(data){
console.log(data)
},
error: function(data){
console.log("error")
console.log(data.statusText)
console.log(data.status)
}
})
});
});
The temp variable uses the values to update which is sent through context data from views.
what is the problem here, its showing error in console.
I want to sumbit a model form with ajax and using model form validation messages:
class ComplaintForm(forms.ModelForm):
class Meta:
model = Complaint
fields = [
'title','body'
]
def clean_body(self):
form_data = self.cleaned_data
body = self.cleaned_data.get('body', False)
if len(body) < 2:
raise forms.ValidationError(u'Please Add Complaint')
return body
def clean(self):
cd = self.cleaned_data
return cd
In my view:
def forms(request):
form = ComplaintForm()
if request.method == "POST":
if request.is_ajax():
form = ComplaintForm(request.POST)
if form.is_valid():
c = form.save(commit=False)
c.user_ip = get_client_ip(request)
c.user = request.user
c.news = news
c.save()
data = serializers.serialize('json', [c,])
else:
data = json.dumps([v for k,v in form.errors.items()])
return HttpResponseBadRequest(data, mimetype='application/json')
return HttpResponse(data, mimetype='application/json')
else:
form = ComplaintForm()
return render_to_response('main/form.html', {'form': form},
context_instance=RequestContext(request))
But, my problem is how could I send data through HttpResponseBadRequest ?
My js is:
$('.complaintform').submit(function(e){
e.preventDefault();
$.ajax({
type: "POST",
url: "/form/",
dataType: "json",
data: $(this).serialize(),
success: function(data) {
$('p').html('ok');
},
error: function(data) {
//how could i insert model form errors here?
}
});
});
Edited my answer. I misunderstood your question initially.
Try this:
$('.complaintform').submit(function(e){
e.preventDefault();
$.ajax({
type: "POST",
url: "/form/",
dataType: "json",
data: $(this).serialize(),
success: function(data) {
$('p').html('ok');
},
statusCode: {
400: function() {
var items = [];
$.each( data, function( val ) {
items.push( val );
});
$('p').html(items.join(""));
}
}
});
});
If that doesn't work, a dirty workaround would be:
1) in the view:
else:
data = json.dumps([v for k,v in form.errors.items()] + ['failed'])
return HttpResponseBadRequest(data, mimetype='application/json')
2) in javascript:
success: function(data) {
if jQuery.inArray("failed", data) {
data.splice("failed", 1);
var items = [];
$.each( data, function( val ) {
items.push( val );
});
$('p').html(items.join(""));
} else {
$('p').html('ok');
}
},
That will work if, for some strange reason, jquery thinks your HttpResponse is 'success'.
I was using MVC3 with AJAX. I was using AJAX within another AJAX. For the first AJAX request, it properly sends to the controller with data. But after returning from the AJAX request, I again posting the same data to another action. But second time the data comes null when coming to the controller. Please help me to fix this issue.
Code
$(document).ready(function () {
$('.deleteitems').live('click', function (e) {
var items = [];
$('.checkall').each(function () {
if ($(this).is(':checked'))
items.push($(this).attr("Id"));
});
var json = JSON.stringify(items);
var perm = $("#Permission").val();
if (items.length != 0) {
if (perm == "True") {
$.ajax({
url: '/ItemControl/ItemControl/Catalogue_Check',
type: 'POST',
dataType: 'json',
data: json,
contentType: 'application/json; charset=utf-8',
success: function (data) {
if (data == "S") {
DelBibsAlso();
}
else {
DelItemsonly();
}
}
});
}
else {
$("#divMes").removeClass("Success");
$("#divMes").addClass("Error");
showError("Sorry you dont have Permission!");
}
}
else {
alert("Select any Items to delete");
e.preventDefault();
}
});
});
function DelItemsonly() {
var items2 = [];
$('.checkall').each(function () {
if ($(this).is(':checked'))
items2.push($(this).attr("Id"));
});
var itemjson = JSON.stringify(items2);
var val = confirm("Are you sure you want to delete these records?");
if (val) {
$.ajax({
url: '/ItemControl/ItemControl/DeleteItems',
type: 'POST',
dataType: 'json',
data: { "id": itemjson, "DelBib": 0 },
contentType: 'application/json; charset=utf-8',
success: function (data) {
e.preventDefault();
$(".t-grid .t-refresh").trigger('click');
$("#divMes").removeClass("Error");
$("#divMes").addClass("Success");
showError("Data Successfully Deleted");
}
});
}
else {
e.preventDefault();
}
}
function DelBibsAlso() {
var items1 = [];
$('.checkall').each(function () {
if ($(this).is(':checked'))
items1.push($(this).attr("Id"));
});
var bibjson = JSON.stringify(items1);
var value = confirm("Do you also want to delete the catalogue record?");
var cond = 0;
if (value) {
var cond = 1;
}
else {
cond = 0;
}
var val = confirm("Are you sure you want to delete these records?");
if (val) {
$.ajax({
url: '/ItemControl/ItemControl/DeleteItems',
type: 'POST',
dataType: 'json',
data: { "id": bibjson, "DelBib": cond },
contentType: 'application/json; charset=utf-8',
success: function (data) {
e.preventDefault();
$(".t-grid .t-refresh").trigger('click');
$("#divMes").removeClass("Error");
$("#divMes").addClass("Success");
showError("Data Successfully Deleted");
}
});
}
else {
e.preventDefault();
}
}
Controller Code
public ActionResult Catalogue_Check(string[] id)
{
DeleteItem weed = new DeleteItem();
int[] ints = id.Select(x => int.Parse(x)).ToArray();
var Matched_BibID = (from asd in Db.Items
where ints.Contains(asd.Id)
select asd.BibId).ToList();
foreach (var idd in ints)
{
var bibid = (from bib in Db.Items where bib.Id == idd select bib.BibId).Single();
var checkbib = (from bibchk in Db.Items where bibchk.BibId == bibid && !ints.Contains(bibchk.Id) select bibchk.Id).Count();
if (checkbib == 0)
{
return Json("S", JsonRequestBehavior.AllowGet);
}
}
return Json("N", JsonRequestBehavior.AllowGet);
}
public JsonResult DeleteItems(string[] id, int? DelBib)
{
//var newid = id.Split(',');
DeleteItem weed = new DeleteItem();
int[] ints = id.Select(x => int.Parse(x)).ToArray();
foreach (var a in id)
{
int sel = Convert.ToInt32(a);
Item item = Db.Items.Single(i => i.Id == sel);
int Sess = Convert.ToInt16(Session["AccId"]);
string AdminName = User.Identity.Name;
bool Exist = Db.RouteOuts.Any(itm => itm.ItemId == item.Id);
if (!Exist)
{
weed.DeleteIt(item, Sess, AdminName);
var bibid = (from bib in Db.Items where bib.Id == item.Id select bib.BibId).Single();
var checkbib = (from bibchk in Db.Items where bibchk.BibId == bibid && !ints.Contains(bibchk.Id) select bibchk.Id).Count();
if (checkbib == 0)
{
Db.ExecuteStoreCommand("update Bibs set Status= 'D' where Id={0}", item.BibId);
Db.SaveChanges();
}
}
}
return Json("S", JsonRequestBehavior.AllowGet);
}
function Test() {
var items1 = [];
$('.checkall').each(function () {
if ($(this).is(':checked'))
items1.push($(this).attr("Id"));
});
//var bibjson = JSON.stringify(items1); **** Loose this line ****
var value = confirm("Do you also want to delete the catalogue record?");
var cond = 0;
if (value) {
var cond = 1;
}
else {
cond = 0;
}
var val = confirm("Are you sure you want to delete these records?");
if (val) {
$.ajax({
url: '/ItemControl/ItemControl/DeleteItems',
type: 'POST',
dataType: 'json',
data: JSON.stringify({ "id": items1, "DelBib": cond }), // **** Items are stringified before posting ****
contentType: 'application/json; charset=utf-8',
success: function (data) {
e.preventDefault();
$(".t-grid .t-refresh").trigger('click');
$("#divMes").removeClass("Error");
$("#divMes").addClass("Success");
showError("Data Successfully Deleted");
}
});enter code here
}
else {
e.preventDefault();
}
I am trying to get X-Editable inline editing of a model in Django. I am simply trying to change attributes of a model instance (in this case, the name of a Dataset object).
I am not sure how to write the view so that it correctly captures the information from the ajax request:
POST /datasets/9/update_name/
{
pk: 3 //primary key (record id)
value: 'The Updated Name' //new value
}
Then save the new name to the Dataset object.
urls.py
# ex: /datasets/3/update_name
url(r'^(?P<pk>\d+)/update_name/$', update_name ,
name='update_name'),
detail.html
<h1 class="page-title center">
{{ dataset.name }}
</h1>
<script>
$('#datasetName').editable({
type: 'text',
pk: {{ dataset.pk }},
url: '{% url 'datasets:update_name' dataset.pk %}',
title: 'Edit dataset name'
params: { csrf: '{% csrf_token %}'} # // This isn't working
});
</script>
views.py
def update_name(request, dataset_id):
# ... Update Dataset object ...
json = simplejson.dumps(request.POST)
return HttpResponse(json, mimetype='application/json')
EDIT:
I believe the problem is that there is no CSRF protection. How can I add this in the X-editable form?
** EDIT 2:
I have also tried this, as per the docs:
<h1 class="page-title center">
{{ dataset.name }}
</h1>
<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;
}
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) {
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'));
}
}
});
$('#datasetName').editable({
type: 'text',
pk: {{ dataset.pk }},
url: '{% url 'datasets:update_name' dataset.pk %}',
title: 'Edit dataset name',
});
</script>
Wow, I spent so much time on this problem!
The shortlist version would be:
{{ project.name }}
And then, call
$('#projectname{{project.id}}').editable();
The correct name for csrf form field is csrfmiddlewaretoken.
I faced this in my PHP Project and I solved it by using the ajaxOptions option. Picked up the CSRF Token from the meta tag and added it to the request header.
ajaxOptions: {
dataType: 'json',
beforeSend: function(xhr){
xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]')
.attr('content'));
}
}
I think the correct one especially if you are working with rails to add
ajaxOptions: {
beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))},
},
inside editable function to be
$('#projectname').editable({
showbuttons: 'bottom',
ajaxOptions: {
beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))},
},
type: 'textarea',
url: '/url/url'
});