Posting JSON to Django views with AJAX - javascript

I am trying to post a JSON object from my client side Javascript to my Django View.
I receive a "500 (Internal Server Error)" When attempting to Post. Does this have to do with the CSRF token? And how can I get around this?
My AJAX
$.ajax({
type: 'POST',
dataType: 'json',
url: '/demo/saved/',
data: {'data': JSON.stringify(finalSelection)},
success: function() {
console.log("Success")
}
});
views.py
def show(request):
data = json.loads(request.POST.get('data', ''))
context = {
'data': data
}
return render(request, 'bill/saved.html', context )
urls.py
urlpatterns = [
path('bill/', views.bill_view, name = 'bill-view'),
path('saved/', views.show, name = 'selected-view'),
]
Appreciate any help!

Assuming its really the CSRF problem you mentioned, since you didn't post the 500 error output, you can simply add the csrf token to your data that is sent in POST request:
$.ajax({
...
data: {
'data': JSON.stringify(finalSelection),
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
...
});

Related

Ajax: How to send FormData inside of json object

To give you a better understanding consider my ajax request:
$.ajax({
url: '{% url "validate-upload-single" %}',
type: "POST",
data: JSON.stringify({
'mainForm': Myform,
'currentForm': 1,
}),
dataType: 'json', // response type
Where:
var Myform = new FormData( $(this)[0] );
The problem is that when i send the request, i get back an empty 'dict' on the server side. Im using Django as my backend
DJANGO VIEW:
print('SORTING THE POST REQUEST')
body = request.body.decode('utf-8')
serialized = loads(body)
print(f'POST: {request.POST}')
print(f'Body: {body}')
print(f'Serialized: {serialized}')
RESULT:
SORTING THE POST REQUEST
POST: <QueryDict: {'{"mainForm":{},"currentForm":1}': ['']}>
Body: {"mainForm":{},"currentForm":1}
Serialized: {'mainForm': {}, 'currentForm': 1}
I've tried $("form").serializeArray() but this only return text data, files seem to be missing
I guess the problem is with contentType header - it should be 'multipart/form-data'. Check this link to make it work with jQuery.ajax
In the .js file you HAVE TO add the fist block of csrf token for properly working.
//Getting csrf token
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 (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
Then you use json in you ajax, getting the template that you want to display by variable here "html_form":
// Submit post on submit
$('#post-form').on('submit', function(event){
event.preventDefault();
console.log("form submitted!") // sanity check
//Send data to server for getting back sorted
$.ajax({
url: '/schedule/sort_group/',
async: true,
type: 'post',
data: { //data sent with the post request
group_field_value: $("#select_group").children("#group-option:selected").val(),
lector_field_value: $("#select_lector").children("#lector-option:selected").attr("name"),
},
dataType: 'json',
success: function (data) {
$("#change_by_select").html(data.html_form);
}
});
});
In the views.py file at the bottom you need to determine the data like that:
data['html_form'] = render_to_string('schedule/select_sort.html', context,
request=request)
return JsonResponse(data)
So I suggest the information that you want to retrieve from the server put into the particular another file, whatever it would be (dictionary or lists or other data structures or html templates).
I hope it would help. Feel free to ask any questions.

How to solve JSONdecode error in ajax django?

I'm receiving JSONdecode error when sending the POST request from ajax to django views.py. The POST sends an array of json. The data from this POST will be used to create the model. Appreciate for any hints.
Error:
Exception Type: JSONDecodeError at /order-confirmation
Exception Value: Expecting value: line 1 column 1 (char 0)
Request information:
USER: ledi12
GET: No GET data
POST: No POST data
FILES: No FILES data
AJAX Request:
var new_array = JSON.stringify(array)
$.ajax({
url: 'http://localhost:8000/order-confirmation',
type: 'POST',
data: '{"array":"' + new_array+'"}',
processData: false,
contentType: "application/json",
dataType: "json",
headers: {"X-CSRFToken":'{{ csrf_token }}'},
success: function (result) {
console.log(result.d);
},
error: function (result) {
console.log(result);
}
});
Views:
#csrf_exempt
def order_confirmation(request):
if request.method == 'POST':
data = json.loads(r"request.body").read()
print(data)
return HttpResponse(status=200)
else:
return render(request, 'main_templates/order_confirmation.html')
The reason you are getting this error is because the JSON library is not able to properly compile the string. There are a couple of things that your code needs to change. Remove 'r' character which is near request.body(). There is no need for 'read()' function in json.loads(). You can preprocess your array into a string and once done, and pass it to ajax. The data field will only have the string. So the ajax code field should look like
data: new_array

JSON object sent from Javascript to Django Views is empty

I'm trying to send some data from Javascript to Django through ajax.
Here is my JS code:
var json_name = {'name': 123}
$.ajax({
method: 'POST',
url: 'my url',
contentType: "application/json",
headers: {
'Content-Type':'application/json',
'X-CSRFToken': "{{ csrf_token }}"
},
data: JSON.stringify(json_name),
success: function (data) {
//this gets called when server returns an OK response
alert("it worked!");
},
error: function (data) {
alert("it didnt work");
}
});
Here is my Views.py:
def myview(request):
if request.is_ajax():
request_data = request.body
# data = json.loads(request.body)
print(request_data)
# print(data)
return render(request, 'candidate/view.html')
else:
return render(request, 'candidate/view.html')
I get the output as b''
When I try to include these lines:
data = json.loads(request.body)
print(data)
I get this error:
TypeError: the JSON object must be str, not 'bytes'
I took some reference from here
Can someone help me with this? If you need any additional information to solve this, I'll be happy to share.
After losing half the hair on my head, I solved it in the following way:
views.py:
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def myview(request):
if request.is_ajax():
if request.method == 'POST':
data = request.POST.get('senddata')
print(data)
return render(request, 'candidate/view.html')
else:
return render(request, 'candidate/view.html')
my JS code:
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
$.ajax({
type: 'POST',
url: 'my url',
// contentType: "application/json",
// headers: {
// 'Content-Type':'application/json',
// 'X-CSRFToken': "{{ csrf_token }}"
// },
dataType: "json",
data: {
senddata: JSON.stringify(json_name),
},
// data: json_name,
success: function (data) {
//this gets called when server returns an OK response
alert("it worked!");
},
error: function (data) {
alert("it didnt work");
}
});
When I run it, it shows it didnt work but I can see the output in my terminal i.e The data was passed.
I tried including the csrf token in the ajax request but it failed. Therefore I used csrf_exempt in my views.
This might be a dirty way of doing things, but it works for now. If anyone has a neat and better answer please post it here!!
I've written a basic testcase on Django 1.11 with Python 3.6 and Python 2.7.
I have been using the following template file to test:
<button>Send data</button>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
$('button').on('click', function(event) {
var data = { name: 123 };
$.ajax({
method: 'POST',
url: '',
contentType: 'application/json',
headers: {
'X-CSRFToken': '{{ csrf_token }}',
},
data: JSON.stringify(data),
success: function() {
console.log('Success!');
},
error: function() {
console.log('Error...');
},
});
});
</script>
And the following route, which delivers the template file and prints any AJAX data:
from django.http import response
from django.shortcuts import render
import json
def index(request):
if request.is_ajax():
request_body = request.body
data = json.loads(request_body)
print(data)
return render(request, 'stackoverflowhelp/index.html')
I've not been able to reproduce the issue.
However, having done more research I found that the json.loads method in Python 3.6 supports bytes objects, while the documentation for Python 2.7 json.loads suggests it only supports string types. While the error you've posted reflects this, I've attempted to make this generate the same error as you're seeing but have had no success.
As you can see, I've not had to whitelist the method from CSRF protection. Based purely on the error you've provided, calling decode on request.body may work:
def index(request):
if request.is_ajax():
request_body = request.body.decode("utf-8")
data = json.loads(request_body)
print(data)
return render(request, 'stackoverflowhelp/index.html')

Ajax request to Django returns 404 not found

I am writing my first project in Django where I now want to make an Ajax request using jQuery to get some data. The problem is that the Ajax request returns:
GET http://localhost:8000/ajax/teams_for_issue/?medIssue=MI6 404 (Not Found)
I am rather certain that the problem is with the URL, and I have gotten the URLs wrong several times before in this project. My Ajax code looks as follows:
var medIssue = _this.issueSelector.val();
$.ajax({
url: '/ajax/teams_for_issue/',
data: {
'medIssue': medIssue
},
dataType: 'json',
success: function(data) {
_this.setTeams(data.teams)
}
});
This is the Django function that I want to send the answer:
def teams_for_issue(request):
medIssue = request.GET.get("medIssue", none)
teams = Team.objects.filter(has_competence=medIssue)
data = {
"teams":teams
}
return JsonResponse(data)
I have defined the following URL
url(r'newpatient/', views.newpatient, name='newpatient'),
url(r'ajax/teams_for_issue/', views.teams_for_issue, name='teams_for_issue'),
Any help on where I go wrong would be much appriciated :)
define type in your ajax request.
$.ajax({
url: '/ajax/teams_for_issue/',
type: "POST",
data: {
'medIssue': medIssue
},
dataType: 'json',
success: function(data) {
_this.setTeams(data.teams)
}
});
also your view should read data from request.POST
def teams_for_issue(request):
medIssue = request.POST.get("medIssue", none)
teams = Team.objects.filter(has_competence=medIssue)
data = {
"teams":teams
}
return JsonResponse(data)

Trying to send a POST request and get json data but getting 400

I'm trying to send an ajax POST request and I've set the content type to be application/json etc. But in the backend I keep getting 400 (BAD REQUEST). What's wrong with the code?
var data = {key0: 'val0', key1: 'val1'};
$.ajax({
type: "POST",
url: 'http://localhost:8000/api/users',
data: data,
success: function(data) {
console.log(data);
},
contentType: 'application/json',
dataType: 'json'
});
Flask:
#usersapi.route('/api/users', methods=['POST'])
def create_user():
#raise Exception(request.headers.get('Content-Type'))
d = dict(request.get_json())
You aren't sending JSON.
You've passed data an object, so it is being serialised as form data.
You need to explicitly convert it to JSON:
data: JSON.stringify(data),

Categories

Resources