I'm trying to post data to a django view using ajax. I have no errors just there is no data returned.
Here is my javascript ajax:
function PostGoal(){
console.log('POSTGOAL!!!')
data_s = {
'csrfmiddlewaretoken': $('input[name="csrfmiddlewaretoken"]').val(),
'goal': { 'name':'gg','box':'sasa' }
}
$.ajax({
method: "POST",
url: "http://127.0.0.1:8000/",//"{% url 'home' %}",//"/",//"{% url 'home' %}",
contentType: 'application/json',
//data: JSON.stringify(data_s),
data: {'QQww': "1"},
//dataType: 'json',//expected type of response
success: function (data) {
console.log('aa'+JSON.stringify(data))
},
error: function(xhr,errmsg,err){
console.log('err: '+JSON.stringify(err)+' msg:'+errmsg)
}
});
}
here is my view function:
def analyzer(request):
if request.method == 'POST':
post_data = request.POST
print(post_data)
print (' ajax:',request.is_ajax())
The boolean request.is_ajax() is ajax is always False request.data or request.POST.data do not exist and same for GET: request.GET is empty. However I can see in the log in the terminal :
[22/Mar/2018 22:15:26] "GET /?QQww=1 HTTP/1.1" 200 9746
so essentially the data are parsed in the url? Thanks in advance.
I read in some other posts that 'method' was the right field to specify the call. For some reason, the parameter 'method' is NOT working and the correct field is 'type':
$.ajaxSetup({
headers: { "X-CSRFToken": '{{csrf_token}}' }
});
$.ajax({
type: "POST",
url: "http://127.0.0.1:8000/",//"{% url 'home' %}",//"/",//"{% url 'home' %}",
contentType: 'application/json',
//data: JSON.stringify(data_s),
data: {'QQww': "1"},
//dataType: 'json',//expected type of response
success: function (data) {
console.log('aa'+JSON.stringify(data))
},
error: function(xhr,errmsg,err){
console.log('err: '+JSON.stringify(err)+' msg:'+errmsg)
}
});
The html button also needs to be of type 'button' not 'submit':
<button type="button" class="btn btn-primary btn-large" id="yesbtn" name="yesbtn" value="yesbtn" onclick="PostGoal();">Yes ยป</button>
I also added the ajax setup for the csrf token to correct the error:
'Forbidden (CSRF token missing or incorrect.): /'
I hope it helps.
Related
Background:
Working in a Django application, I have a template that performs an action (makes a payement) using an external API. The API call is done in Javascript.
On Success, the API returns a response object. This works well on tests.
function makePayment(applicationAmount) {
let paymentEngine = RmPaymentEngine.init({
key: 'abcd'
firstName: '{{ user.f_name }}',
onSuccess: function(response) {
console.log('callback Successful Response', response);
// TODO: Add a function to post the payment records to the database
// response from the API contains a dictionary like (read json) object
// how can I get that response object in Python and use those response
// object values to update a django model database records
},
onError: function(response) {
console.log('callback Error Response', response);
// TODO: Add a function to throw an error message
},
onClose: function() {
console.log("closed");
}
});
}
Question:
How can I get that onSuccess response object variables in Python and use those response object values to update a django model database records?
Looked at this link: How do I return the response from an asynchronous call? but can't seem to implement my need.
I'd be happy to be directed to a simple resource that explains the procedure, not something very involved that takes hours to understand.
Using ideas from #Lag11 and #Arount and a wonderful tutorial here, I created 2 function based views, one to just serve the 'page' the other to handle the 'page post to DB'.
Summary, I did this in the template:
function makePayment(applicationAmount) {
let paymentEngine = RmPaymentEngine.init({
key: 'abcd'
firstName: '{{ user.f_name }}',
onSuccess: function(response) {
console.log('callback Successful Response', response);
// start new additions
data = {
"payer_email": "{{ user.email }}",
"payer_phone": "{{ user.phone }}",
"payment_amount_total": response.amount,
}
$.ajax({
type: 'POST',
url: "{% url 'post_purchase_form' %}",
data: data,
onSuccess: function (response) {
console.log('callback db post Successful', response);
},
error: function (response) {
// alert the error if any error occured
alert(response);
}
})
// end new additions
},
onError: function(response) {
console.log('callback Error Response', response);
// TODO: Add a function to throw an error message
},
onClose: function() {
console.log("closed");
}
});
}
And this in the views.py:
def application_form_view(request):
user = request.user
form = ApplicationForm(instance=user)
return render(request, 'application_form.html', {'form': form, 'user': user})
def post_application_form_view(request):
# request should be ajax and method should be POST.
if request.is_ajax and request.method == "POST":
# get the form data
form = ApplicationForm(request.POST, request.FILES)
# save the data and after fetch the object in instance
if form.is_valid():
instance = form.save()
# serialize in new FormPurchase object in json
ser_instance = serializers.serialize('json', [ instance, ])
# send to client side.
return JsonResponse({"instance": ser_instance}, status=200)
else:
# some form errors occured.
return JsonResponse({"error": form.errors}, status=400)
# some error occured
return JsonResponse({"error": "unknown errors"}, status=400)
Hi i'm currently have my api that use this simple-JWT package for jwt token authentication, it worked great. But now when i try to call the api from the django website app using Ajax in which is from a page user already logged in but it still required me to use the jwt access_token.
My ajax call from the page user already logged in:
$.ajax({
type: "POST",
url: "/api/add_favorite/" + property_id + "/",
beforeSend: function (xhr) {
xhr.setRequestHeader('Authorization', 'Bearer {{ refresh_token }}');
},
success: function (data) {
if (data.code == 200) {
alert('added to favorite');
replace_part_1 = '<a id="mylink2" href="#" value="' + property_id +'"><i class="fas fa-heart fa-lg" style="color: red" title="Remove from favorite"></i></a>'
$("a[value='" + property_id + "']").replaceWith(replace_part_1);
}
}
});
Now i don't want to set the header with authorization since in the page user already logged in so the session is already set.
So i tried to add Django Session authentication to the the api like so:
#api_view(['POST'])
#authentication_classes([SessionAuthentication, JWTAuthentication])
#permission_classes([IsAuthenticated])
def add_favorite(request, property_id):
if request.method == 'POST':
try:
favorite_property = Property.objects.get(pk=property_id)
if request.user.is_authenticated:
login_user = request.user
if not login_user.properties.filter(pk=property_id).exists():
login_user.properties.add(favorite_property)
return JsonResponse({'code':'200','data': favorite_property.id}, status=200)
else:
return JsonResponse({'code':'404','errors': "Property already exists in favorite"}, status=404)
except Property.DoesNotExist:
return JsonResponse({'code':'404','errors': "Property not found"}, status=404)
My Ajax after removed the header :
$.ajax({
type: "POST",
url: "/api/add_favorite/" + property_id + "/",
},
success: function (data) {
if (data.code == 200) {
alert('added to favorite');
replace_part_1 = '<a id="mylink2" href="#" value="' + property_id +'"><i class="fas fa-heart fa-lg" style="color: red" title="Remove from favorite"></i></a>'
$("a[value='" + property_id + "']").replaceWith(replace_part_1);
}
}
});
and i removed the set header from the Ajax call now i get 403 return code :
Failed to load resource: the server responded with a status of 403
(Forbidden)
My settings:
REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
'rest_framework.authentication.SessionAuthentication',
),
# 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}
I don't know why the session authentication doesn't work since the Ajax call is from the page user already logged in.
Thank for reading!
Because you're adding Authentication header on your ajax requests, Django automatically use TokenAuthentication if Authentication exists on the request header. Remove it to use SessionAuthentication.
There might be a problem when you're switch to use SessionAuthentication is that Django will reject your unsafe requests if there is no CSRF token, more detail here
This is what My ajax call looks like
$.ajax({
url:"{% url 'handsontable' %}",
data: {'getdata': JSON.stringify(hot.getData())},
dataType: 'json',
type: 'POST',
success: function (res, status) {
alert(res);
alert(status);
},
error: function (res) {
alert(res.status);
}
});
This is what my django view looks like.
if request.method == 'POST':
request_getdata = request.POST.get('getdata', 'None')
return HttpResponse(request_getdata)
The alerts in ajax return the data and "success". But my HttpResponse returns "None".
Any idea why it is not passing the data through? Thanks!
First off you are trying to POST to a html file
url:"/utility_tool/decisions/solution_options/handsontable.html",
Instead, it should be a url to a view.
Second, the ajax post request should have the csrftoken in it's header and you can set it up like this:
<script type="text/javascript">
// using jQuery get csrftoken from your HTML
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function (xhr, settings) {
// if not safe, set csrftoken
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
$.ajax({
url: "{% url 'name of the view from urls.py' %}",
data: {
// here getdata should be a string so that
// in your views.py you can fetch the value using get('getdata')
'getdata': JSON.stringify(hot.getData())
},
dataType: 'json',
success: function (res, status) {
alert(res);
alert(status);
},
error: function (res) {
alert(res.status);
}
});
</script>
And in your django view:
# views.py
from django.http import JsonResponse
def someView(request):
if request.method == 'POST':
# no need to do this
# request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
request_getdata = request.POST.get('getdata', None)
# make sure that you serialise "request_getdata"
return JsonResponse(request_getdata)
And in your urls:
# urls.py
urlpatterns = [
# other urls
path('some/view/', views.someView, name='name of the view in urls.py'),
]
I cannot add comments because I do not yet have up to 50 reputations as demanded by StackOverflow. This is supposed to be a comment under the answer provided by #abybaddi009. He has done a very good job thus far but the answer needs a finishing touch.
In the view
request_getdata = request.POST.get('getdata', None) does not work
but this does
body = request.body.decode('utf-8')
data = body[3]
request.body.decode('utf-8') returns a string which would look something like getdata=your_data you can then use string manipulation techniques or regex to extract your data.
What you need to do is :
code for ajax call ( in js file) to send the data to the view
jQuery.ajax(
{
'url': "url_pattern_in_urls_py_file/",
'type': 'POST',
'contentType': 'application/json; charset=UTF-8',
'data': JSON.stringify({'updated_data':your_data_val}),
'dataType': 'json',
'success': function ( return_data ) {
//success body
}
}
);
code in django view with respect to above POST ajax call to receive the data
import json
if request.method == 'POST':
updatedData=json.loads(request.body.decode('UTF-8'))
I added return false; at the end of the ajax request and it worked. I printed out the values in the view instead of using HttpResponse.
I use angularJS $http send data to django and the method is POST
this is my controller.js
registerApp.controller('registerCtrl', function($scope, $http) {
$scope.submitRegisterForm = function() {
if ($scope.registerForm.$valid) {
console.log($scope.user);
$http({
method: 'POST',
url: '.',
data: $scope.user,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
} else {
return console.log(3333);
}
};
});
this is my views.py in django
if request.method == 'POST':
print request.POST
but the result of print is
<QueryDict: {u'{"username":"bob","password1":"123123","password2":"123123","email":"cot#q.com"}': [u'']}>
why the data is a Key of the dict?
and wher is the [u''] come from??
Just because you've called it form-encoded data, doesn't mean it actually is. In fact it looks like you're posting JSON. Drop that header and get the data by doing json.loads(request.body).
I have this code in AngularJS:
myApp.controller('LoginCtrl', function($scope, $http){
$scope.formData = {};
$scope.doLogin = function(url, pass){
$http({
url: url,
method: "POST",
data: $.param($scope.formData)
}).success(function(data) {
console.log(data)
});
}
});
And in the beckend (Flask), I have this:
def user_authenticate():
login = request.args.get('login')
password = request.args.get('password')
print login, password
The problem is that request.args come empty.
UPDATE
After have a lot of problems with this, I solve using another Stackoverflow answer. So, I got this code:
ANGULARJS
$scope.doLogin = function(url, pass){
$http({
url: url,
method: "POST",
headers: { 'Content-Type': 'application/json' },
data: JSON.stringify(data)
}).success(function(data) {
console.log(data)
});
}
FLASK
def view_of_test():
post = request.get_json()
param = post.get('param_name')
OLD VERSION
I just figured that I need to change my code to this:
AngularJS:
myApp.controller('LoginCtrl', function($scope, $http){
$scope.formData = {};
$scope.doLogin = function(url, pass){
$http({
url: url,
method: "POST",
data: $.param($scope.formData),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).success(function(data) {
console.log(data)
});
}
});
Just include the 'Content-Type' header.
Flask:
def user_authenticate():
login = request.form.get('login')
password = request.form.get('password')
print login, password
Instead of use request.args, use request.form.