How to handle request json data in flask - javascript

I would like to send json formatted data from my html page to a url on the click of a button, but currently the data is not getting updated to the url. I've included here a small subset of the data i'm trying to post. The GET method works fine for posting initial output to the url. The result of the ajax request is the alerted error output. How can I use POST to successfully update the output to the url?
The html:
<button type="submit" class="btn-sm btn-success btn-space" id ="commitButton" name="commitButton" value="enter">Commit</button>
Javascript:
<script>
document.getElementById('commitButton').onclick = function() {
$.ajax({
url: "/processjson",
type:'POST',
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
},
"dataType": "json",
"data": {"schema": {"fields":[{"name":"index","type":"integer"},{"name":"OB_TIME","type":"datetime"},{"name":"LATITUDE","type":"number"},{"name":"LONGITUDE","type":"number"}]}, "data": [{"index":0,"OB_TIME":"2015-09-03T00:00:00.000Z","LATITUDE":21.9,"LONGITUDE":-152.0}]},
"contentType": "application/json",
success: function(result) {
alert('ok');
},
error: function(result) {
alert('error');
}
})
};
</script>
Flask:
#app.route('/processjson', methods=['GET','POST'])
#login_required
def processjson():
if request.method == 'GET':
return jsonify({'result':'Test'})
# getting the table data when the commit button is pressed
if request.method == 'POST':
# gets jsonified data and convert it to a python data structure (dictionaries)
data = request.get_json()
fields = data['schema']['fields']
tableData = data['schema']['data']
return jsonify({'result':'Success!','tableData' : tableData})

Place the json data inside the request body.
You can access the request body with request.form.get('data') to get a json string. This can be load to a dict using json.load(json_str).

request.get_json() parse form data as json, but this would work if you are submitting as form data. Looking at the JS snippet, it looks like you are not submitting it as form data (you are making an ajax call), so your data will be available in the property request.json

you can use like this : request.json

Related

Django CSRF Token missing from ajax request

edit for future reference
Solved:
on fetch request in script.js, I used Headers instead of headers, hence the "Missing csrf token" instead of missing or incorrect
So i'm building a project in Django for a "password manager" I've built my modules and correctly implemented the Item insertion via Django ModelForm, with csrftoken and all that.
Now i need to make an ajax request for updating the fields of the Item, and wanted to do on the same page
so from Js when opening a LoginItem to edit the content I send a GET request as such
//fetch django for a form, and it sends back pre filled with initial values
fetch(`edit/login=id`)
.then((response) => response.text())
.then((form) => {
const edit_form = document.createElement('form');
edit_form.setAttribute("method", "post");
edit_form.setAttribute("id", "edittest");
edit_form.innerHTML = form;
//append the form
then in script.js, on submit:
fetch(`edit/login=id}`, {
method : "PUT",
Headers:{
//or "X-CSRFToken":event.target.querySelector('[name=csrfmiddlewaretoken]').value
"X-CSRFToken": getCookie("csrftoken"),
"Content-type": "application/json",
},
mode:"same-origin",
body : JSON.stringify(body),
})
.then((response) => response.json())
.then((data) => {
console.log(data)
})
in Views.py
def edit_login(request, id):
if request.method == GET:
login = Entry.objects.get(id=id)
// setting initial values for the form
initial = {
"title": login.title,
"username": login.username,
"password": login.password,
"note": login.note,
"folder": login.folder,
"protected":login.protected,
"favorite": login.favorite,
}
// setting the initial values to the ModelForm
form = LoginForm(initial=edit)
return render(request, 'vault/new_item.html', {"entry_form": form, 'uri_field': uri})
else if request.method == "PUT":
if request.user == login.owner:
data = json.loads(request.body)
print("test") # execution does not reach here
return JsonResponse({"message": "Succesfully edited"}, status = 200 ) # oppure 204 = No content
I get Forbidden (CSRF token missing.): /edit/login=27
In the PUT fetch request I also tried instead of getCookie()
using "X-CSRFToken":event.target.querySelector('[name=csrfmiddlewaretoken]').value to get this form's csrf input value that gave me a different csrftoken than the previous.
Also if I inspect every element I open, i see each of them has a different csrftoken (ok, different requests, so I could fathom the error Incorrect Token, but the missing error i don't understand.
Also, if anyone has a hint on how to do this in an easier way, that'd be great, I have limited knowledge
The simplest way I have solved this problem is by including the {{csrf_token}} value in the data without using #csrf_exempt decorator in Django(The decorator marks a view as being exempt from the protection ensured by the middleware.):
var csrftoken = "{{csrf_token}}";
//Sample ajax request
$.ajax({
url: url,
type: 'POST',
headers:{
"X-CSRFToken": csrftoken
},
data: data,
cache: true,
});

Ajax call run by form submission and will pass data to a separate views.py template

I am building a web application using Django. I have a search function on my index page. When a user submits the form an AJAX call should be executed. This AJAX call should take all the needed data from the form and pass it over to a completely separate views.py template that will make API GET requests using that data and build a new page using that separate template.
As of right now it is not loading the separate views.py template, I am unsure if I am passing the data correctly however I do see /searchresults?searchType=data1&executeLocation=data2 in my console because my AJAX call is returning on success currently. It is safe to assume that I have all the data needed in the data1 and data2 variables, I just need help redirecting to the new page and passing the data along with the redirect.
My code:
urls.py
# The home page
path('', views.index, name='home'),
# Search results page
path('searchresults', views.search_results, name='searchresults'),
AJAX
function getSearchResults(searchType,executeLocation,csrf_token)
{
$.ajax(
{
type: $(this).attr('method'),
url: "searchresults", //The URL you defined in urls.py
data :
{
searchType: searchType,
executeLocation: executeLocation,
csrfmiddlewaretoken: csrf_token
},
dataType: 'text',
success: function(response) // currently executes success (but not correct outcome)
{
console.log(response);
alert('winner winner chicken dinner');
},
error: function(response)
{
console.log(response);
alert('failure');
}
}).done(function(data)
{
console.log(data)
});
}
index.html
<form method="POST" action="{% url 'searchresults'%}">
...
<button type="submit" onclick="getSearchResults('data1','data2','{{csrf_token}}')">Submit</button>
</form>
views.py
def search_results(request):
context = {}
context['requestData'] = request.POST
html_template = loader.get_template('search/searchresults.html')
return HttpResponseRedirect(html_template.render(context, request))
An acceptable solution should be able to do the following tasks:
Redirect the user to the search_results page
Pass the form data to the search_results page somehow
After assistance from #AminMir I was able to get a working solution. It turns out I do not need AJAX but I did need a forms.py file.
view.py
def index(request):
context = {'segment': 'index'}
context['SearchForm'] = SearchForm()
return HttpResponse(html_template.render(context, request))
forms.py
from django import forms
class SearchForm(forms.Form):
searchType = forms.CharField(max_length = 100)
executedLocation = forms.CharField(max_length = 100)
searchValue = forms.CharField(max_length = 100)
index.html
<form method="POST" action="{% url 'searchresults'%}">
{% csrf_token %}
{{ SearchForm.as_ul }}
<input type="submit" value="submit">Search</button>
</form>
This form will then post my data to my views.py for my search_result page which is left unchanged.

How to Parse LocalStorage JSON object in Django View from Ajax?

I am trying to submit localstorage data via a POST request using the below jquery ajax method. How should I write my view so I can Parse my JSON object and get a hold of "product_id" to execute the below command in my Django view. Please see a copy of my view below.
Trying since one week, but I failed to fix the issue
Is there any better way of achieving this ?
My Ajax:
$(document).ready(function() {
var compare = localStorage.getItem("comparisionItems");
var compareObj = JSON.parse(compare);
var data_url = window.location.href;
console.log(compare)
console.log(compareObj)
$.ajax({
url: data_url,
type: "POST",
data: {'compare_id': compareObj },
headers: { "X-CSRFToken": $.cookie("csrftoken") },
success: function (result) {
console.log("Success")
},
});
});
and My Views:
def compare(request):
is_ajax = request.headers.get('X-Requested-With') == 'XMLHttpRequest'
if is_ajax and request.method == "POST":
compare_id= request.POST.getlist('compare_id[itemIds]')
product = get_object_or_404(Products, id=compare_id)
context={ 'product':product}
return render (request, './compare.html', context)
Actually my localStorage is on following format:
("comparisionItems"({ images: products, itemIds: itemIds }));
Can you please help me how can I pass itemIds to views and return item from views for the itemsIds?
Console log for console.log(compareObj)
https://imgur.com/MxdZrgy
since .is_ajax() is deprecated you cant use that, but you can check if the request is an XMLHttpRequest like below.
from django.shortcuts import get_object_or_404
def compare(request):
is_ajax = request.headers.get('X-Requested-With') == 'XMLHttpRequest'
if is_ajax and request.method == "POST":
compare_id = request.POST.get('compare_id')
product = get_object_or_404(Products, product_id=id)
context={ 'product':product,}
return render (request, './ecommerce/compare.html', context)
note; the get_object_or_404 is just a shortcut for:
try:
product = Products.objects.get(product_id=id)
except:
raise Http404

How to send json data from Angularjs post to Django view?

I need to send json data using a POST request from Angularjs to my Django view.
I need to get data from database using this json as json format.
I tried some examples using from net resources:
JS Code:
$http({
method: 'POST',
url: '/mycard/list',
data: $.param({test: json})
});
Python Code(Django View):
def product_list(request):
if len(request.META['QUERY_STRING']) > 0:
data = request.body
data = json.loads(data)
print data
else:
f = open('./mytest.txt','r')
data = f.read()
return HttpResponse(data, mimetype='application/json')
But it returns 403 error and sometimes it returns 500 error(INTERNAL SERVER ERROR)
Service Code
var promise = $http({
method: 'post',
url: '/mycard/list',
data:data,
contentType:'application/json; charset=UTF-8',
});
return promise;
Python rest api
#csrf_exempt
#api_view(['GET','POST'])
def product_list(request):
if request.method == 'POST':
try:
stream = StringIO(request.body)
data = JSONParser().parse(stream)
except ValueError:
return Response(json.dumps(ValueError, default=json_util.default))
return Response(json.dumps(data, default=json_util.default))
else:
return Response("failure")
your json data should be formatted by JSON.stringify() like this:
$http({
method: 'POST',
url: '/mycard/list',
data: JSON.stringify({test: json})
});
403 Forbidden maybe because of an invalid CSRF token
500 : You might be not posting the data in the format that the backend is expecting. Can you please inspect and see what is the error response it is giving.

My Json get cut off when sent with Ajax

I'm using angular to save new data on the database, I take the data from my inputs, put it in a object and I convert it to a Json, I send it by POST, but my JSON gets cut off and I have no clue why is it happening.
var myJson = angular.toJson(myObject);
$http({
method: 'POST',
url: 'http://url/file.php',
data: {
'data': myJson
}
})
.success(function (data){
console.log(data);
})
My file.php has a var_dump($_POST) in it, and it shows that:
[
{
"uuid":"56456456456456456456465456"
},
{
"store_name":"",
"store_email":"",
"store_facebook":"",
"contact_name":"John Doe",
"contact_email":"email#email.com",
"contact_facebook":"http://localho
Angular's http post method sends whatever data it is passed to. You should check your generated json data after
var myJson = angular.toJson(myObject); using console.log(myJson);
and that itself must be cut off.

Categories