How to send data to the view in Flask using AJAX? - python

Please help...
I am trying to upload a csv or excel file, and using an Ajax call trying to send it to Flask along with an integer.
HTML Form:
<form id="testFileForm" method="POST" action="{{ url_for('auto') }}" enctype="multipart/form-data">
{{ fileUploadForm.csrf_token }}
<label class="connect choosefile setInput config-button-size " >
<i class="fa fa-file" aria-hidden="true"></i>
<span id="testFileLabel">Choose Test Data</span>
{{ fileUploadForm.file(class="input1 btn btn-primary", id="testFile") }}
</label>
<label class="form-label" style="padding-left:10px ;">
<input class="btn btn-primary config-button-size" id="testFilebtn" type="submit" value="Process">
</label>
</form>
Ajax Call:
$('#testFilebtn').click(function() {
var file = document.getElementById("testFile").files[0];
alert(file)
var data = {
file: file,
id : 1
}
alert('file loaded')
$.ajax({
data: data,
type: "POST",
url: "auto",
"Content-Type": 'application/json',
dataType: 'json',
success: function(response) {
alert(response)
},
});
});
View:
#app.route('/auto', methods=['POST', 'GET'])
#login_required
def auto(dataset_id=None):
fileUploadForm = FileUploadForm()
if request.method=='POST' and fileUploadForm.validate_on_submit():
try:
file = request.files['file']
id = request.form['id']
print('id')
print(id)
except UploadNotAllowed:
return redirect(url_for("auto"))
# return redirect(url_for("auto"))
return "te"
I get error while retrieving the id, which indicates I am also not receiving file from ajax call.
Error:
werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
KeyError: 'id'
I am new to Ajax calls, some help would highly be appreciated...

I believe you could do it like this :
var fd = new FormData($('#testFileForm')[0]);
fd.append( 'id', 1 );
$.ajax({
url: 'http://example.com/',
data: fd,
processData: false,
contentType: false,
type: 'POST',
success: function(data){
alert(data);
}
});
Notes:
Setting processData to false lets you prevent jQuery from automatically transforming the data into a query string.
See the docs for more info.
Setting the contentType to false is imperative, since otherwise jQuery will set it incorrectly.

Related

Posting file upload via AJAX returns empty dictionary on Flask side

I have a Flask app that was working until I added login functionality. The issue I'm having is I have a modal that the user can upload a file with.
HTML
<p>Upload Photo</p>
<form method="POST" name="upload_pic" id="upload_pic" enctype="multipart/form-data">
<input type="file" class="custom-file-input" name="exampleInputFile" id="exampleInputFile" aria-describedby="fileHelp">
<label class="custom-file-label" for="exampleInputFile">
Select file...
</label>
<button type="button" class="btn btn-success" data-dismiss="modal" id="AddNotesSubmit">Submit</button>
Then an AJAX call to upload the file:
// add notes post
$('#AddNotesSubmit').on('click', function(e) {
var notes = $("#note_text").val();
var schedule_id = $("#noteSchID").text();
console.log(notes);
e.preventDefault();
$.ajax({
type: "POST",
url: "/",
data: { AddNotes: "", schedule_id: schedule_id, notes: notes },
success:function(response){
$('#response').text(JSON.stringify(response));
}
});
var fullPath = $("#exampleInputFile").val();
var filename = fullPath.replace(/^.*[\\\/]/, '');
const form = $('#upload_pic')[0];
const pic = new FormData(form);
console.log(form);
console.log(pic);
console.log(filename);
if (filename != '') {
$.ajax({
type: "POST",
url: "/upload_pic",
data: pic,
processData: false, // tell jQuery not to process the data
contentType: false // tell jQuery not to set contentType
});
}
$('#modalAddNotes').modal('hide');
});
});
And finally the Flask code I'm using to debug:
#app.route('/upload_pic', methods=['POST'])
def upload_pic():
print(' request.files: %s' %request.files)
files = request.files.get('files[]')
print(' files: %s' %files)
The command line output on the python side is:
request.files: ImmutableMultiDict([])
files: None
So it's returning an empty dictionary. Previously, when I used:
uploaded_pic = request.files['exampleInputFile']
It worked, but now with that code included it throws a 400 error because the 'exampleInputFile' is invalid key in the request.files dictionary. I removed the #login_required from the route and it didn't change anything.
From my point of view, it is difficult to see why your code is not working. In your example, the form tag is not closed. Also, you didn't describe how your javascript code is executed. Although I assume that you are using a click event, I tested your code with a submit event. I have come to the conclusion that the code works.
Here is the variant I used for testing:
<p>Upload Photo</p>
<form method="POST" name="upload_pic" id="upload_pic" enctype="multipart/form-data">
<input type="file" class="custom-file-input" name="exampleInputFile" id="exampleInputFile" aria-describedby="fileHelp">
<label class="custom-file-label" for="exampleInputFile">
Select file...
</label>
<button type="submit" class="btn btn-success" data-dismiss="modal" id="AddNotesSubmit">Submit</button>
</form>
<script
src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
crossorigin="anonymous"></script>
<script type="text/javascript">
$(document).ready(function() {
$('form[name="upload_pic"]').submit(function(event) {
event.preventDefault();
const form = event.target;
const formData = new FormData(form);
$.ajax({
type: 'POST',
url: '/upload_pic',
data: formData,
processData: false,
contentType: false
}).done((data) => {
console.log(data);
})
});
});
</script>
#app.route('/upload_pic', methods=['POST'])
def upload_pic():
if 'exampleInputFile' in request.files:
file = request.files['exampleInputFile']
if file.filename != '':
# handle file here!
return jsonify(success=True)
return jsonify(success=False)

How to populate a django form in a POST request with data from an ajax call?

I'm sending form data via an ajax call after user hits submit button and then handling this request in my views, but the form is empty. How can I populate the form?
This is my code:
My JS file:
var csrftoken = getCookie('csrftoken'); //getCookie is a csrf_token generator
var form = $(this).closest('form')
$.ajax({
url: form.attr("action"),
data: { // if I change this line to data: form.serialize(), it works fine!
csrfmiddlewaretoken : csrftoken,
form: form.serialize(),
},
type: form.attr("method"),
dataType: 'json',
success: function (data)
{
//Do a bunch of stuff here
}
})
My views:
def task_edit(request, pk):
task = get_object_or_404(Task, pk=pk)
if request.method == 'POST':
task_form = NewTaskForm(request.POST) # This is empty!
else:
task_form = NewTaskForm(instance=task) # This for populating the edit modal, works fine!
I'm not doing the data: form.serialize() because I need to send additional data with the ajax request. How do I get this working?
You can write as below:-
$form_data = $("#idofform").serialize();
And then in ajax
data : $form_data+'&key=value',
You can use services like https://www.formkeep.com to capture form data using AJAX.
This may be a good idea if you are already using a JavaScript framework, you want to add validation logic, or you don't want to redirect the user after they submit the form.
You can submit to FormKeep using a standard AJAX request. To ensure the request does not cause a redirect, be sure to set the Accept header to application/javascript.
Given the following form:
<form id="newsletter-signup" action="http://formkeep.com/f/exampletoken" method="POST" accept-charset="UTF-8">
<input type="hidden" name="utf8" value="✓">
<input name="email" type="email">
<input value="Submit" type="submit">
</form>
Here's an example of how to submit a form with jQuery:
$(function() {
$('#newsletter-signup').submit(function(event) {
event.preventDefault();
var formEl = $(this);
var submitButton = $('input[type=submit]', formEl);
$.ajax({
type: 'POST',
url: formEl.prop('action'),
accept: {
javascript: 'application/javascript'
},
data: formEl.serialize(),
beforeSend: function() {
submitButton.prop('disabled', 'disabled');
}
}).done(function(data) {
submitButton.prop('disabled', false);
});
});
});
That's it. Once your data is securely captured in FormKeep you can easily store it, manage it or connect it with 1000s of other systems like Google Docs and Hubspot and Mailchimp.

Django is not taking GET input in AJAX call

I am trying to take username input and return in ajax call whether the username is taken or not in Django. But the method in DJango is not taking the input. I am sharing the code here.
URL.py
url(r'^search_username/$', user.views.search_product, name="search_username"),
script + HTML
{% load staticfiles %}
{% block content %}
<form method="post">
{% csrf_token %}
<input name="search" id="search" type="text"/>
<button type="submit">Sign up</button>
</form>
{% endblock %}
$("#search").change(function () {
var username = $(this).val();
$.ajax({
url: '/search_username/',
data: {
'username': username
},
dataType: 'json',
error: function(){
alert('failure');
},
success: function (data) {
if (data.is_taken) {
alert("A user with this username already exists.");
}
}
});
});
Views.py
def search_username(request):
print('Entered into search')
username = request.GET.get('search', None)
print(username)
data = {
'is_taken': allproductlist.objects.filter(product_name_english__iexact=username).exists()
}
return JsonResponse(data)
The problem is it prints Entered into search.But when I print username it shows NOne. Can anyone please specify what is happening ?
Your Ajax is sending the data as "username" but your Python is looking for "search".
you are sending username in ajax request but you are getting search in views.py.
you can Update your ajax code:
$("#search").change(function () {
var username = $(this).val();
$.ajax({
url: '/search_username/',
data: {
'search': username
},
dataType: 'json',
error: function(){
alert('failure');
},
success: function (data) {
if (data.is_taken) {
alert("A user with this username already exists.");
}
}
});
});
2nd way is that you can change in views.py.
username = request.GET.get('username', None)

Flask Ajax returns POST HTTP/1.1" 400 error while uploading

Hi all I have a simple form with an upload button like this.
<form role="form" id="sf" name = "sf" method="post"
enctype="multipart/form-data" action="javascript:void();">
<input type="file" id="file" name="file" class="file">
</form>
my js looks like this.
$('#file').bind('change', function() {
var form_data = new FormData($('#suject-form')[15]);
var request = $.ajax({
url: "/upload",
type: "POST",
contentType: "application/json",
cache: false,
processData: false,
async: false,
data: {
file: new FormData($('#suject-form')[0]),
state: 'testing'
},
dataType: "json",
})
.done(function(data){
console.log(data);
})
return false;
});
-
When I try to get the file data it keeps giving me the 400 error,
-
#app.route('/upload', methods=['POST'])
def upload():
if request.method == 'POST':
state= request.form['state']
files = request.files['file']
# if I leave out file it returns but fails when leave in files
return jsonify(result=[state])
Anyone know what I'm doing wrong? thanks!

Django Ajax form submission pointing to a 403 Forbidden

I'm allowing users to remove posts through ajax. Posts have a boolean field live_until_removed. When set to false, the post disappears.
When clicking remove I'm given a 403, referencing:
xhr.send( ( s.hasContent && s.data ) || null );
How do I get this to run smoothly? Why this this error happening?
js:
$('#removeForm').submit(function() { // catch the form's submit event
$.ajax({
data: $(this).serialize(),
type: $(this).attr('method'),
url: $(this).attr('action'),
success: function(response) {
$('.close-post').html(response); // update the DIV
console.log(response);
},
error: function(response){
console.log(response);
}
});
return false;
});
template:
<div class="close-post">
{% if not post.live_until_removed %}
<form class="" id="removeForm" method="POST" action="">
<button type="submit" class="btn">Remove</button>
</form>
{% else %}
<button class="btn">Removed</button>
{% endif %}
</div>
views.py:
def post(request, id):
...
if request.is_ajax():
try:
post = Post.objects.get(id=id)
post.live_until_removed = False
post.save()
response = simplejson.dumps({"status": "Removed"})
except:
pass
You might have missed to send CSRF token in your request. Look at here; Django-Ajax

Categories

Resources