I have the following AJAX POST below, for some reason looking at my logging (server side) the request it's sending is is blank {} not JSON data is sent. I have exhausted all possible server side issues this is a client side issue with the script not sending data. why?
bootstrap-wizard.js found here -> GitHub
My page code overrides the script submit:
<script src="{{ STATIC_URL }}js/bootstrap-wizard.js"></script>
<script type="text/javascript">
$(function() {
var options = {width:1000};
var wizard = $("#some-wizard").wizard(options);
$("#open-wizard").click(function() {
wizard.show();
});
wizard.on("submit", function(wizard) {
$.ajax({
url: '/api/v1/rewards/campaigns/',
type: 'POST',
contentType: 'application/json; charset=UTF-8',
data: $('#wizard').serialize(),
beforeSend: function (request) {
request.setRequestHeader("X-CSRFToken", $('input[name="csrfmiddlewaretoken"]').val());
},
success: function(data, textStatus) {
wizard.submitSuccess(); // displays the success card
wizard.hideButtons(); // hides the next and back buttons
wizard.updateProgressBar(0); // sets the progress meter to 0
console.log('success');
},
error: function(errorThrown){
// data = JSON.parse(errorThrown.responseText);
wizard.submitError(); // display the error card
wizard.hideButtons(); // hides the next and back buttons
console.log(errorThrown);
}
});
});
});
</script>
This is my form:
<form action="" method="post" class="form-horizontal" id="wizard" enctype="application/json" >
{% csrf_token %}
<div class="wizard" id="some-wizard">
<h1>{% trans "Setup Wizard" %}</h1>
<div class="wizard-card" data-cardname="card1">
<h3>{% trans "General" %}</h3>
etc, etc <=== all my form fields here
</div>
serialize() returns key/value formatted URL encoded data (x-www-form-urlencoded), not JSON. If your server side requires JSON then you need to change your data parameter:
$.ajax({
...
data : JSON.stringify({ input_a : 'value a', input_b : 'value b' }),
...
});
See this question for how to convert a form into JSON automatically.
Related
Does anyone know why I am getting 500 internal error when I try to call an Ajax function? I tried to send the response from view.py to Ajax function in 2 ways: JsonResponse (see else from view.py) and also with HttpResponse (see if from View.py).
My Hmtl form does have a csrf_token, so I added the header in ajax function, but still got 500 internal erorr. The data is saved into database but the response is not sent to ajax function.
View.py
## Ajax
#login_required
def SubmitModal(request):
if request.method == 'POST':
text = request.POST['Text']
date = request.POST['DatePicker']
time = request.POST['TimePicker']
T = SText()
T.User = request.user
T.Text = text
T.STime = date + ' ' + time
T.save()
return HttpResponse(json.dumps({'success': True}), content_type="application/json")
else:
return JsonResponse({'success': False})
file that contains ajax
$(document).ready(function () {
// Show the modal window when a button is clicked
$('#open-modal').click(function () {
$('#modal').modal('show');
});
// Close the modal window when a button is clicked
$('.close-modal').click(function () {
$('#modal').modal('hide');
});
// Handle the form submission
$('#modal-form').submit(function (event) {
event.preventDefault(); // Prevent the form from being submitted
var formData = $(this).serialize(); // Get the form data
// Submit the form data to the server using an AJAX request
$.ajax({
type: 'POST',
url: '/submit/',
headers: {'X-CSRFToken': '{{ csrf_token }}'},
data: formData,
dataType: "json",
success: function (response) {
if (response.success) {
$('#success-message').show();
} else {
$('#error-message').show();
}
},
error: function (xhr, status, error) {
console.log(error);
}
});
$(".textarea-input")[0].value = '';
$(".date-input")[0].value = '';
$(".time-input")[0].value = '';
});
});
If you're reproducing this in a non-production environment, you can set DEBUG=True in the settings file. Then when you make the call from your browser, the response will include details about what the issue is. You can also set the ADMINS variable to send exception tracebacks to the specified emails when they're encountered. More details here.
You can view the data being sent and received in the developer tools of the browser you are using.
A function on our website fires for all of our forms. It uses jquery's serializearray method and works great.
I need to add a form with a file input, and serializearray doesn't handle files. I'm not new to Python and Django, but I am new to Jquery. And I'm having trouble adapting the function.
Since the formData class handles files, I thought I could change "data: serializedform" to "data: new formData(form)".
When I did that, Chrome's console displayed "Uncaught TypeError: Illegal invocation". Firefox's console displayed "Uncaught TypeError: 'append' called on an object that does not implement interface FormData."
Do I need to convert the FormData object to another type?
A snippet follows:
uploadfile.html:
function postAndLoad(form, url, panelDivID, btnName){
var serializedForm = $(form).serializeArray();
return request = $.ajax({
url: url,
dataType : 'html',
cache: 'false',
type : 'POST',
data: serializedForm, //data: new FormData(form) produces an error.
success: function (data) {
console.log("Completed POST");
error: function(data) {
console.log('There was a problem in postAndLoad()');
console.log(data);
}
});
return false;
};
…
<form enctype="multipart/form-data" onsubmit="postAndLoad(this, '{% url 'UploadFile' %}', 'panel_upload'); return false;" method='post'>
{% csrf_token %}
{{ form | crispy}}
<div class="row w-100">
<input class="btn" type='submit' name="form1btn" value="button" />
</div>
</form>
forms.py:
class UploadFile(forms.Form):
uploadFile = forms.FileField(label="Select file to upload")
sampleText = forms.CharField(label="Enter some text")
We're creating a web application using Flask. On one html page, users answer some questions (using <form>). During this process, they are asked to click a button on the page for a few times when they receive random popup notifications. In the .html file, we write javascript functions to save the timestamps of users clicking on the button into an array.
We hope to store both the user's answers and the timestamps of clicking the button. Now from .html to .py, we pass answers using request.form and pass the array of timestamps using ajax json (request.json). The request.form works very well but the request.json always gives a None. We have tried request.get_json(), request.get_json(force=True), request.get_json(silent=True), but none of them works.
Our codes are like the following:
in trial.py:
from flask import (Blueprint, flash, g, redirect, render_template, request, url_for, jsonify, json)
from werkzeug.exceptions import abort
import csv
from flaskr.db import get_db
bp = Blueprint('trial', __name__, url_prefix='/trial')
#bp.route('', methods=('GET', 'POST'))
def trial():
if request.method == 'POST':
if "Q1" in request.form:
## this part retrieves data from request.form
## skip the details in the following
db = get_db()
db.execute(
'INSERT INTO trial (...)', (...))
db.commit()
timestamps = request.json
print(timestamps) ### This is always a None
return render_template('study/trial.html')
In trial.html:
{% extends 'base.html' %}
{% block header %}
<h1>{% block title %}Trial{% endblock %}</h1>
{% endblock %}
{% block content %}
<!-- Skip non-related details in the following -->
<button class="NotificationButton" onclick="popup()">I Got A Notification</button>
<div>
<form name="TrialQuestions" id="TrialQuestions" method="post">
<!-- skip the details of the questions and input for answers -->
</form>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="{{url_for('static', filename='jquery.js') }}">\x3C/script>')</script>
<script>
var timestamps = {"trial":[]};
function playAudio() {
<!-- skip non-related details -->
timestamps["trial"].push(remaining);
}
function popup(){
<!-- skip non-related details -->
timestamps["trial"].push(remaining);
}
function timeUp(){
document.TrialQuestions.submit();
$.ajax({
type: "POST",
url: "{{ url_for("trial.trial") }}",
contentType: "application/json",
data: JSON.stringify(timestamps),
dataType: "json",
success: function(response) {
console.log(response);
},
error: function(err) {
console.log(err);
}
});
alert("Time Is Up! Your Answers Have Been Submitted!");
}
</script>
{% endblock %}
The console.log(response); in trial.html works well, but the timestamps = request.json in trial.py always gives a None. We have searched and tried the suggestions from the following posts but none of them solves the problem:
Passing Javascript array in Python Flask
Get the data received in a Flask request
How to send information from javascript to flask route
Can anyone give some hints? Thanks a lot!
Your form submit results in the page being reloaded and the template being transmitted again as html from the server.
An asynchronous javascript request is only ended when the callback for success or error is called. The transmission of the data is not waited for.
function timeUp() {
console.log("sending data to " + "{{ url_for('trial.trial') }}")
$.ajax({
type: "POST",
url: "{{ url_for('trial.trial') }}",
contentType: "application/json",
data: JSON.stringify(timestamps),
dataType: "json",
success: function(response) {
console.log(response);
// The data has now been successfully transferred.
// document.TrialQuestions.submit();
},
error: function(err) {
console.log(err);
}
});
}
When specifying the data type, the query expects exactly this as an answer. See also here.
For this reason, I am returning a response in json format.
from flask import render_template, request, jsonify
#bp.route('/', methods=('GET', 'POST'))
def trial():
if request.method == 'POST':
print('got a post request')
if request.is_json: # application/json
# handle your ajax request here!
print('got json:', request.json)
return jsonify(success=True) # answer as json
else:
# handle your form submit here!
print(request.form)
return render_template('trial.html')
AJAX has the advantage that you can send and load data sets without reloading and rendering the whole page.
Within a transmission, the data is formatted in a predefined format. When you submit a form you use the type "application/x-www-form-urlencoded" or "multipart/form-data". For JSON it is "application/json".
Depending on the selected format, either the query "request.json" returns a "None" or "request.form" is an empty dictionary.
The structure of your data set depends on your requirements.
The following is a suggestion that is similar to the original approach of a form.
function timeUp() {
const data = {
"data": $("form[name='TrialQuestions']").serializeArray().map(elem => {
return [elem["name"], elem["value"]];
}),
"ts": timestamps,
};
$.ajax({
type: "POST",
url: "{{ url_for('trial.trial') }}",
contentType: "application/json",
data: JSON.stringify(data),
dataType: "json",
success: function(response) {
console.log(response);
},
error: function(err) {
console.log(err);
}
});
}
Should you just want to send a form, for example because you want to do a redirect. Add one or more hidden fields to the form and fill in their value before submitting.
<form name="TrialQuestions" method="post">
<label for="q1">Question 1</label>
<input name="q1" id="q1" value="a1" />
<input name="ts" type="hidden" />
</form>
<script>
function timeUp() {
document.forms["TrialQuestions"]["ts"].value = timestamps.join();
document.forms["TrialQuestions"].submit();
}
</script>
... update to the question from myself.
As posted in the question, request.form can work but request.json will give a "None".
Following Detlef's approach, according to what I tried on my side, request.json can work but request.form will give a "None". Please correct me if I mistaken anything.
So, now I propose a trade-off approach: package the form and the timestamps into one ajax JSON object. The code is now like this:
<div>
<form name="TrialQuestions" id="TrialQuestions">
<label for="Q1">Question 1</label>
<input name="Q1" id="Q1">
<!-- skip the questions -->
</form>
</div>
<script>
var TrialQuestionAnswers = [];
var timestamps = [];
var formAndTimestamps = [];
function timeUp(){
TrialQuestionAnswers = [document.getElementById("Q1").value, ..., document.getElementById("Q13").value];
formAndTimestamps.push(TrialQuestionAnswers);
formAndTimestamps.push(timestamps);
$.ajax({
type: "POST",
url: "{{ url_for("trial.trial") }}",
contentType: "application/json",
data: JSON.stringify(formAndTimestamps),
dataType: "json",
success: function(response) {
console.log(response);
},
error: function(err) {
console.log(err);
}
});
alert("Time Is Up! Your Answers Have Been Submitted!");
}
</script>
It can work, but maybe this is not the most efficient solution. Better idea is much appreciated!
i am getting a form with user parameters when i make an AJAX call to a page which later on is submiited to a url so that i can create a session for the same user in advance and when
that person goes to that site he sees his name there.
i created one div tag with id "abc_session", assign that form (whose id is fm1) to it,and submitted the form.
now as per the requirement session is created but page automatically gets redirected to that site url to which form is submitted.i just don't wan't that to happen.
can anyone please suggest something..or some workaround
the form that AJAX returns looks something like this:
<html>
<body onload="document.fm1.submit();return false">
<form name = "fm1" method="post" action = "https://abcd.com/abc ">
<input type=hidden name ="name" value="xyz">
<input type=hidden name ="login_parameters" value="CDF5D71C5BDB942EE2FB6C285B8DEBFE4C5675137B615CD2276571813AAC872AC8942E26B71026414BED1FEA09427D0B20A50FE2F70032D2E5B382598EC3C71D73EAB4ECBF7273A73BEB98ACEA4A0B775E7772BDC7C6746C355">
</form></body>
</html>
and the script goes like this
$(document).ready(function() {
function callwebsite()
{
$.ajax({
url: "/NASApp/benemain/website",
data: {},
type:"POST",
dataType: 'text',
cache: false,
success: function (data) {
alert("Call made to website.. ");
console.log(data);
document.getElementById("abc_session").innerHTML=data;
document.fm1.submit();
},
error : function(response){
console.log('ERROR');
},
statusCode : {
500 : function() {
console.log('500 error');
window.location.reload(true);
},
401 : function() {
console.log('401 error');
window.location.reload(true);
},
404 : function(){
console.log('400 error');
}
}
});
}
callwebsite();
tried extracting the data and maiking another ajax call as suggested by quentin but getting this error "Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource.This can be fixed by moving the resource to the same domain or enabling CORS."
$.ajax({
url: lcAction,
data: {partner_id:lcPartner,login_parameters:lcLP },
type:"POST",
headers:{'Access-Control-Allow-Origin': '*'},
dataType: 'text',
//crossDomain: true,
//cache: false,
success: function(data)
{
alert("success");
},
error:function(response)
{
//alert("error");
console.log(response);
}
});
You are submitting the form:
document.getElementById("abc_session").innerHTML=data;
document.fm1.submit(); // Here
Don't do that.
Extract the data from it and make another Ajax request.
You should use e.preventDefault() as soon as you submit the form.
I am trying to implement file upload using ajax with Django but facing some problem.
When the user tries to upload the files after selecting the file and submitting the form, then as per my understanding , an ajax request should be send to the server using POST method ,but in my case a POST request is being made to the server, but the server is not able to identify it as an ajax request and browser is redirected to http://<server>:<port>/upload/ and the contents on this page are as follows.
{"status": "error", "result": "Something went wrong.Try Again !!"}
Django Version: 1.6.2
Python Version: 2.7.5
Also, testing on Django Development Server.
views.py
def upload(request):
logging.info('Inside upload view')
response_data = {}
if request.is_ajax():
logging.info('Is_AJAX() returned True')
form = UploaderForm(request.POST, request.FILES)
if form.is_valid():
logging.info('Uploaded Data Validated')
upload = Upload( upload=request.FILES['upload'] )
upload.name = request.FILES['upload'].name
upload.save()
logging.info('Uploaded Data Saved in Database and link is %s' % upload.upload)
response_data['status'] = "success"
response_data['result'] = "Your file has been uploaded !!"
response_data['fileLink'] = "/%s" % upload.upload
return HttpResponse(json.dumps(response_data), content_type="application/json")
response_data['status'] = "error"
response_data['result'] = "Something went wrong.Try Again !!"
return HttpResponse(json.dumps(response_data), content_type='application/json')
Template
<form id="uploadForm" action="/upload/" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input id="fileInput" class="input-file" name="upload" type="file">
<input type="submit" value="Post Images/Files" />
</form>
Javascript 1:
$('#uploadForm').submit(function(){
var formData = new FormData($(this)[0]);
$.ajax({
url: '/upload/',
type: 'POST',
data: formData,
async: false,
success: function (data) {
alert(data)
},
cache: false,
contentType: false,
processData: false
});
return false;
});
Javascript 2
var options = {
url: '/upload/',
type: "POST",
error: function(response) {
alert('Something went Wrong. Try Again');
},
success: function(response) {
if ( response.status == 'success' ) {
alert('success');
}
}
};
$('#uploadForm').ajaxSubmit(options);
Question:
1) Why is Django not able to recognize the ajax request and value of request.is_ajax() is always False.
2) Even if the server doesn't recognize ajax request why is my browser getting redirected to another page ?
There is another similar question here but with no result.
This works for me. You need a jquery.form.js
$("#uploadForm").submit(function(event) {
$(this).ajaxSubmit({
url:'{% url upload_file %}',
type: 'post',
success: function(data) {
console.log(data)
},
error: function(jqXHR, exception) {
console.log("An error occurred while uploading your file!");
}
});
return false;
});
Here's the similar question here with answers.
Make sure that javascript code block
$('#uploadForm').submit(function(){
var formData = new FormData($(this)[0]);
$.ajax({
url: '/upload/',
type: 'POST',
data: formData,
async: false,
success: function (data) {
alert(data)
},
cache: false,
contentType: false,
processData: false
});
return false;
});
loaded after your uploadForm html form in DOM on page. In your case seems you trying to bind submit handler with form element which not yet loaded so when you click, it send simple POST request.
1) why is_ajax() not working?
Have you included the JQuery form plugin (jquery.form.js) ? ajaxSubmit() needs that plugin.
Take a look at http://jquery.malsup.com/form/
If it's already done, you might take a look at the HTTPRequest object
Django Documentation says HttpRequest.is_ajax()
Returns True if the request was made via an XMLHttpRequest. And if you are using some javascript libraries to make the ajax request, you dont have to bother about this matter. Still you can verify "HTTP_X_REQUESTED_WITH" header to see if Django received an XMLHttpRequest or not.
2) Why page redirects?
As I said above, JQuery form plugin is needed for handling the ajax request and its call back. Also, for ajaxSubmit() you need to override the $(#uploadForm).submit()
$('#uploadForm').submit( function (){
$(this).ajaxSubmit(options);
return false;
});
Hope this was helpful :)