This is a follow-up question from here: there I learned how to upload a file, process it and then populate the website again with its content using AJAX and FormData. For example, if I have a file data.csv like this:
A,B,C
1,3,4
2,4,2
I can pass it using AJAX and FormData
<form method="POST" enctype="multipart/form-data" id="fileUploadForm">
<div class="custom-file">
<input id="myfile" name="myfile" type="file" class="custom-file-input">
<label for="myfile" class="custom-file-label">
Choose file...
</label>
</div>
</form>
// the javascript part
var form = $('#fileUploadForm')[0];
var formdata = new FormData(form);
$.ajax({
type: "POST",
enctype: 'multipart/form-data',
url: "/_get_table",
data: formdata,
processData: false,
contentType: false,
cache: false,
timeout: 600000,
and get:
I can then easily fetch this using
file = request.files['myfile']
and convert it into a dataframe using
df = pd.read_csv(file)
My question is now how I would do this, if I want to pass additional parameters (not only the file). Here it is suggested to use
var formdata = new FormData();
formdata.append("myform", form)
formdata.append("myvalue", 10)
which gives
and the headers
How do I now collect the info correctly? I can get myvalue like this
val = request.form['myvalue']
but I have not found a way to access and read myfile. If I e.g. try
file = request.files['myform']
I get
werkzeug.exceptions.HTTPException.wrap..newcls: 400 Bad
Request: KeyError: 'myform'
I also tried other solutions from here but without success.
The problem is because you didn't add your file to the FormData correctly.
As you are using multipart/form-data, your payload should be one file and some form-data. But in your screenshot, as you can see, you were adding one object.
To solve this problem, actually you can directly add your value to the original FormData:
var formdata = new FormData(form);
formdata.append("myvalue", 10);
Related
The data is stored in a dataframe as "S\u00c3o Miguel", but the data is returned from template as "S%C3o Miguel", and Python can't find it on the dictionary. How can I solve this?
I developed an application that gets data (as well as the labels) from the database and plots them on charts using the Highcharts library.
When the user clicks on one of the bars of the charts, the label of it is sent back to the server, which returns some values.
The problem is: when the data is first loaded from the database, it is stored in memory in a dataframe, where "S\u00c3o Miguel" is one of the values, but when the user clicks on a chart and the JQuery request is made to the server, it is sent back as "S%C3o Miguel". Due to this, the code can't find this key on the dataframe in the memory.
I've tried to encode the string as UTF-8 with encodeuricomponent on JavaScript prior to sending it back to the server, but no success.
The template already has the tag.
def getFromDatabase():
[...]
wfarm_names = pd.read_sql(query, engine) #Gets the data from the database
return (list(wfarm_names['CL_NAME'].unique())) #Returns a list with all the keys. The value that causes the problem is returned as 'S\u00c3o Miguel'
def getData(request, cluster):
#In this case, cluster is returned from screen as 'S%C3o Miguel'
wfarm_names = list(general_frame[general_frame['CL_NAME'] == cluster]
#problem occurs here
The JQuery request is bellow:
$.ajax({
url: "http://127.0.0.1:8000/monitors/turbine-getter/" + cluster + "/",
data: {
csrfmiddlewaretoken: "{{ csrf_token }}",
},
dataType: "json",
success: function(data){
window.maxmin_vals = data.maxminvals;
cont.style.display = "inline-block";
pb.style.display = "none";
window.pointsDict = {};
window.current_buffers = data.latlong;
window.current_cluster = cluster;
)
},
error: function (rs, e) {
alert('Sorry, try again.');
}
});
It looks like jQuery is encoding the url, you can decode like this:
>>> from urllib import parse
>>> decoded = parse.unquote(url)
I am developing a web app using angular, python and Flask.
In my app there is a form where the user need to enter some data and to upload his photo.
I want to implement the file upload to the server using angular.
I saw that I need to use the FormData() and to bind the data from the HTML to angular using "watch".
The javascript part is clear.
I don't understand how can I get the data from the Python side.
This is my HTML -
<form enctype="multipart/form-data" ng-submit="submitGuideDetailsForm()">
<div class="form-group">
<label for="usr">Add your photo:</label>
<input type='file' class="form-control" name='file' onchange="angular.element(this).scope().uploadFile(this.files)">
</div>
</form>
This is my angular -
$scope.uploadFile = function(files) {
$scope.file = new FormData();
$scope.file.append("file", files[0]);
};
$scope.submitGuideDetailsForm= function() {
$http.post('/uploadFile', $scope.file, {
headers: {'Content-Type': undefined },
transformRequest: angular.identity
}).success(function(results)
{
$log.log('success load file')
}).error(function(error)
{
$log.log('error load file!!!!!')
$log.log(error);
});
};
I want to get the file on the server side, using python and flask -
#app.route('/uploadFile', methods=['POST'])
def uploadFile():
json_data = request.json
print(json_data)
status = 'success'
return jsonify({'result': status})
I don't know how to get the data from the 'request' object.
request.json does not work.
Please advice me what am I doing wrong.
How can I get the data from the 'request' object?
Do I need to encode the data to a file?
How do I send the data back to client? Do I need to encode it back?
I did not find a full example using angular and python/flask uploading a file to server, saving it and than downloading it to the client.
Thanks a lot,
Dina
the file can be get byfile = request.files['file']
after that,
you can get the filename by file.filename.encode("utf8")
The command 'request.files' work
The gets me the following object -
ImmutableMultiDict([('file', <FileStorage:
u'12132638_10153196350425732_1151540092606190338_o.jpg'
('image/jpeg')>)])
I don't understand how can I save it on the server.
How do I get only the file name out of this object
And how do I send it back to the client side?
Thanks a lot, Dina
Use request.files and .filename atrribute
file = request.files['file']
fileName = file.filename
#to store it on server use getvalue() and write it to the file object
filedata = file.getvalue()
with open('abc.png') as f:
f.write(filedata)
I'm trying to allow the click trigger to do some backend dynamic csv creation, and then return it back to the user as a csv download file. I guess I'm not sure how I should write out the return statement other than just putting return response. I'v come across some other posts saying that I would need to set my url to a hidden iframe?? Not sure what this means though. Any tips?
Ajax looks like this:
$('#download-maxes').on('click', function(){
$.ajax({
type: "POST",
url: "{{request.path}}download/",
dataType: 'json',
async: false,
data: JSON.stringify(workouts),
success: function(workoutData) {
console.log(workoutData);
},
error:function(error){
console.log(error);
}
});
});
And my django view looks like this:
def download(request):
#(... a lot of mongo stuff here & other things defined)
workouts = json.load(request.body)
response = HttpResponse(content_type='text/xlsx')
response['Content-Disposition'] = 'attachment; filename="team_maxes.xlsx"'
writer = csv.writer(response)
writer.writerow(['Name', 'Date', 'Workout', 'Max'])
for member in team_members.all():
for wo in workouts:
wo_data = db.activity_types.find_one({"name": wo["name"]})
best_wo = db.activity.find_one({"u_id": member.user.id, "a_t": str(wo_data["_id"]), "is_last": 1}) or 0
member_name = member.user.first_name + ' ' + member.user.last_name
try:
max_stat = best_wo["y_ts"]
except:
max_stat = 0
try:
date = best_wo["e_d"]
except:
date = ""
workout_name = wo_data["name"]
writer.writerow([member_name, date, workout_name, max_stat])
return response
You don't need to use ajax. Since you are POSTing some json data to your view, just make a form with a hidden text input, and set it's value to the json data. Then make a regular submit button in the form.
When the form gets submitted, and the server responds with Content-Disposition: attachment; filename="team_maxes.xlsx", your browser will automatically trigger a download.
If you decide to go this route, Keep in mind:
You are using a regular html form now, with the POST method, so you must remember to use django's {% csrf_token %} tag inside of it.
You will probably have set the input's value to your json string, right before submitting the form.
Your workouts json gets sent in a form input. So, assuming you named your input "workouts", in your view you would do something like:
workouts = json.loads(request.POST.get('workouts'))
Plus a bunch of error checking, of course.
Been at this for hours, giving up and posting in the hopes someone can help me out. Maybe this is a terribly stupid idea but I:
Have an html page that I modify using some jQuery controls (adding classes to a large list of items individually on click, filling in textareas, changing page title, etc..
On click of a save button want to do something like :
$('#save').click(function() {
myhtml = $('html').html();
$.ajax({
type: "POST",
url: "http://127.0.0.1:5000/parse_data",
data: myhtml
});
});
Then on the Python/Flask side:
#app.route('/parse_me', methods=['GET', 'POST'])
def parse_me():
if request.method == "POST":
#determine new filename based on #header id
#save new file with request.form data? request.something data??
#using the new filename
I read over the flask docs, and tried many many variations. I'm thinking my problem primarily lies in how I'm sending & then unpacking the data. The closest I got was using:
data: JSON.stringfy(myhtml)
and then on the python side I could "see" that data by doing
print request.values
inside the parse_me() method. Any help would be appreciated. It seemed like the "simplest" solution to what I want to accomplish: I modify the dom with jQuery then ship off my changes to flask to package them into a new file on the server.
Solved!
changed :
$('#save').click(function() {
myhtml = $('html').html();
$.ajax({
type: "POST",
url: "http://127.0.0.1:5000/parse_data",
data: {html:myhtml} // made into a hash for retrieval
});
});
on the python side :
#app.route('/parse_data', methods=['GET', 'POST'])
def parse_data():
# updated: get value for key "html", encode correctly
data = request.form.get("html").encode("utf-8")
# do whatever with the data
return "Data retrieved"
Very easy.. loving Flask!
I'm having some issues getting AJAX communication working using the Bottle framework. This is my first time using AJAX, so it's likely I just have the basics wrong. Hopefully a Bottle/AJAX guru can point this novice in the right direction. Here is the code I'm using:
#!/usr/bin/env python
from bottle import route, request, run, get
# Form constructor route
#route('/form')
def construct_form():
return '''
<html>
<head>
<script type="text/javascript">
function loadXMLDoc()
{
xmlhttp = new XMLHTTPRequest();
xmlhttp.onReadyStateChange = function()
{
if(xmlhttp.readyState == 4 && xmlhttp.status == 200)
{
document.getElementById("responseDiv").innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open("GET", "/ajax", true);
xmlhttp.send();
}
</script>
</head>
<body>
<form>
<input name="username" type="text"/>
<input type="button" value="Submit" onclick="loadXMLDoc()"/>
</form>
<div id="responseDiv">Change this text to what you type in the box above.</div>
</body>
</html>
'''
# Server response generator
#route('/ajax', method='GET')
def ajaxtest():
inputname = request.forms.username
if inputname:
return 'You typed %s.' % (inputname)
return "You didn't type anything."
run(host = 'localhost', port = '8080')
There are a few issues here.
Javascript is case sensitive. XMLHTTPRequest should be XMLHttpRequest. You should have seen an error about this in your Javascript console.
onReadyStateChange should be onreadystatechange.
If you fix the above two issues your AJAX call will work, but you will only ever get the 'You didn't type anything.' response. This is because you are using GET. You need to change your code so the form values are posted using the POST method.
Also, why aren't you using jQuery to do AJAX? It would make your life much easier. :)