Flask - Get a dataframe to download as csv - javascript

On a button click, I want to use values from from multiple input fields in html and use that as parameters to download some data. Then I am trying to convert that to csv and have it download as a csv file. I found in the javascript that the response has the data in csv format, but no file is getting downloaded. What am I missing?
.html file:
***html I left out to keep this short***
<input type="button" value="Download CSV" onclick="downloadacsfile()">
.js file:
function downloadacsfile() {
var acs_variable = document.getElementById('variableid').value;
var state = document.getElementById('stateselection').value;
var acs_type = document.getElementById('acs_type').value;
var year = document.getElementById('years').value;
$.get("/api/acs_download", {acs_variable: acs_variable, state:state, acs_type:acs_type, year:year }, function(response){
console.log(response.exist);
});
}
.py file:
app.add_url_rule('/api/acs_download', 'acs_download', acs_download, methods=['GET'])
def acs_download():
acs_variable = request.args['acs_variable']
state = request.args["state"]
acs_type = request.args["acs_type"]
year = request.args["year"]
params = {'acs_type': acs_type,
'year': year,
'variable': acs_variable,
'state': state}
###Gets data from 3rd party API to csv format###
datafetch = fetcher.Fetcher(api_key)
data = datafetch.get_census_data(**params)
data = data.to_csv(index=False)
return Response(
data,
mimetype="text/csv",
headers={"Content-disposition":
"attachment; filename=testfile.csv"})

You need the user to redirect to the location where the file is to be downloaded. So instead of making a get request, you instead turn window.location into the right url.
So turn this...
$.get("/api/acs_download", {acs_variable: acs_variable, state:state, acs_type:acs_type, year:year }, function(response){
console.log(response.exist);
});
Into this:
var params = {acs_variable: acs_variable, state:state, acs_type:acs_type, year:year}
window.location.href = '/api/acs_download?' + $.param( params )

Related

Ajax not sending data to PHP script

I have a web app that is basically a huge form that will eventually be transformed into a pdf. When the form is submitted, all the input gets sent to a php file that stores them as variables to be added to the pdf. Some of the data I need on the pdf is calculated in JavaScript, so I am using ajax to send those calculated variables to the same php file that the form sends its data to. The ajax call is not sending the data to the php script. I tried to echo some of the variables, but nothing shows up. Here is my ajax call:
$.ajax({
url: 'FMpdf_values.php',
method: 'POST',
data: {elevChartImg : elevChartImg, azChartImg : azChartImg, power_rating : power_rating, antWeight : antWeight, antennaWithRadomeWeight : antWithRadomeWeight,
epa : epa, radome : radome, deicer : deicer, thetaCol : thetaCol, afAmpCol : afAmpCol, dbCol : dbCol, product : product, channelFM : channelFM,
antLongDescription : antLongDescription, antShortDescription : antShortDescription},
success:function(data){
console.log(data);
}
});
The PHP file is just setting the variables to $_POST['some_data'], then that file is included in the PHP file that creates the pdf. I am relatively new to both PHP and ajax, so I apologize if this is an easy fix. I am wondering if it is even possible to get values from the HTML form and ajax in the same file?
FMpdf_values.php:
<?php
//PHP file for getting the values needed for the PDF
//All html element variables are added here, while calculated values are passed through AJAX
header("Content-Type: application/json", true); //For accepting JSON data
//HTML Element Variables
$projectName = $_POST['projectTitle'];
$customer = $_POST['customer'];
$location = $_POST['location'];
$antModel = $_POST['tlantennaModel'];
$specCode = $_POST['specNumber'];
$createdBy = $_POST['completedBy'];
$notes = $_POST['notes'];
$date = date("F j, Y");
$revDate = $_POST['revisionDate'];
$freq = $_POST['channelNum'];
$wavelength = "11807.22891";
$gainVal = $_POST['tlhorPeakPower'];
$erpVal = $_POST['tlhorERP'];
$beamtilt = $_POST['beamTiltVal'];
$firstNull = $_POST['firstNull'];
$secondNull = $_POST['secondNull'];
$rfInput = $_POST['rfInputs'];
$antennaHeightFt = $_POST['antennaHeightFt'];
$antennaHeightMt = $_POST['antennaHeightMt'];
$CORHeightFt = $_POST['CORHeightFt'];
$CORHeightMt = $_POST['CORHeightMt'];
$ovrHeightFt = $_POST['overallHeightFt'];
$ovrHeightMt = $_POST['overallHeightMt'];
$vertLineType = $_POST['tlTypeVertSelect'];
$vertLineLengthFt = $_POST['tlvertft'];
$vertLineLengthMt = $_POST['vertLengthMeters'];
$vertAttenFt = $_POST['tlvertatten'];
$vertAttenMt = $_POST['tlVertAttenMt'];
$horLineType = $_POST['tlTypeHorSelect'];
$horLineLengthFt = $_POST['tlhorft'];
$horLineLengthMt = $_POST['horLengthMeters'];
$horAttenFt = $_POST['tlhoratten'];
$horAttenMt = $_POST['tlhorattenmt'];
$transLineLosskW = $_POST['tranlinelossKW'];
$transLineLossdB = $_POST['tranlinelossdb'];
$transLineEff = $_POST['tlefficiency'];
$antInputPowerkW = $_POST['antennaInputPowerkw'];
$antInputPowerdB = $_POST['antennaInputPowerdBk'];
$isoTranLosskW = $_POST['isoLosskw'];
$isoTranLossdB = $_POST['isoLossdB'];
$filterLosskW = $_POST['filterLosskw'];
$filterLossdB = $_POST['filterLossdB'];
$systemLosskW = $_POST['systemLosskw'];
$systemLossdB = $_POST['systemLossdB'];
$totalLosskW = $_POST['totallosskw'];
$totalLossdB = $_POST['totallossdB'];
$TPOkW = $_POST['poweroutputkw'];
$TPOdB = $_POST['poweroutputdB'];
$systemEff = $_POST['otherSystemEfficiency'];
//Variables from AJAX
$elevChartImg = $_POST['elevChartImg'];
$azChartImg = $_POST['azChartImg'];
$power_rating = $_POST['power_rating'];
$antWeight = $_POST['antWeight'];
$antWithRadomeWeight = $_POST['antWithRadomeWeight'];
$epa = $_POST['epa'];
$radome = $_POST['radome'];
$deicer = $_POST['deicer'];
$thetaCol = $_POST['thetaCol'];
$afAmpCol = $_POST['afAmpCol'];
$dbCol = $_POST['dbCol'];
$product = $_POST['product'];
$channelFM = $_POST['channelFM'];
$antLongDescription = $_POST['antLongDescription'];
$antShortDescription = $_POST['antShortDescription'];
//ThetaCol, afAmpCol, & dbCol are currently JSON encoded objects
$thetaCol = json_decode($thetaCol);
$afAmpCol = json_decode($afAmpCol);
$dbCol = json_decode($dbCol);
die(print_r($_POST));
You are basically calling your PHP script 2 times.
At the first time you are firing up an ajax call (Your php script executes at the server side and PDF generator code runs and generates invalid PDF, as you don't have the form data yet)
Second time the actual form is submitted, your PHP script executes again, this time you don't have the AJAX data, so again the target PDF will be invalid)
Instead of sending data in 2 parts (one part using form POST and another part using AJAX POST), have some hidden fields in your form, fire the javascript calculation function on click of your submit button, fill up the hidden fields and then submit the form. This way you get all the data at one go.
Let me know if that make sense and if you are able to proceed ahead or do you need some sort of code samples..

generate csv in JS and send it using ajax request POST to flask

I am trying to create a CSV file in JS using my code table2csv. Then I want to send it to flask using an ajax request and return it back again to the client.
But as I try to send the file to server it returns the error that ajax can't find my file.
I used console.log to check if my file is created and it is. I am stuck and don't know what to do anymore, since I am pretty new to ajax requests so any help would be great.
This is my JS part and what I am doing currently:
//On Update click renders table to csv, activates the be_filter and reopens it in the filtered_file.html
var isClicked;
jQuery("#update").on('click', function(){
var response = confirm('Are you sure you want to UPDATE rows ?');
if(response == true){
isClicked = $('#my_id').table2csv();
$.ajax({
type:'POST',
url:"{{url_for('update_file')}}",
data: {'data': isClicked},
success: function(result){
console.log(result);
},
error: function(error){
console.log(JSON.stringify(error));
}
});event.preventDefault();
//window.location.href='/update_file';
}else{
return false;
}
});
And the flask call:
#app.route('/update_file', methods=['GET', 'POST'])
#login_required
def update_file():
'''Opens the filtered_file page but with updated file'''
clicked = None
if request.method == 'POST':
clicked = request.form['data']
file_to_filter = pd.read_csv(clicked, sep=';', engine='python', encoding='utf_8_sig')
table1 = update_csv(file_to_filter)
table2 = table1.to_html(classes='my_class" id = "my_id')
return render_template('3_filtered_file.html', data=table2)
EDIT: console.log() for the error message :
POST http://127.0.0.1:5000/update_file 500 (INTERNAL SERVER ERROR)
{"readyState":4,"responseText":"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n <head>\n <title>FileNotFoundError: [Errno 2] No such file or directory: '"Auftragsdatum","OrderNo","ReferenceOrder","Pos","Quantity","ArtNo","ManufactureNo","ProductName","ReferencePosition","NetPerPiece","InvoiceNo","DeliveryNoteNo","SerialNumbers","Manufacturer","CI","Type","Import_ID","State","Supplier","NetPerPieceSale","OU","Modified_Date","Added_by","Modified_by","isSupplier","isManufacturer"\\n"01.04.2019","7027856072","a","100","1","2099882","GS1900-24HP-EU0101F","ZYXEL GS1900-24HP 24P GbE L2 PoE Switch","CLINO","251,09","950347427","6054042579","S182L37002129","ZYXEL","sel","","","716","ALSO","","OU00100","11-11-2019 09:58","admin","","","BPT07939"\\n"01.04.2019","7027856072","bg","200","1","3074862","EAP225 V3","TP-LINK AC1350 WLAN Dual Band Gigabit AP","CLINO","64,56","950347427","6054042579","218B410001725","TP-LINK","sel","","","716","ALSO","","OU00100","11-11-2019 09:58","admin","","","BPT07134"\\n"01.04.2019","7027856072","cd","300","1","7003581","","Mautgebühr","nan","2,09","950347427","6054042579","","","sel","","","716","ALSO","","sel","11-11-2019 ...
EDIT 2 ** this is my code for **table2csv:
(function ($) {
const _trim_text = (text) => {
return text.trim();
};
const _quote_text = (text) => {
return '"' + text + '"';
};
function convert(tb){
let output = "";
let lines = [];
$(tb).find('thead>tr').each(function () {
let line = [];
$(this).find('th:not(th:eq(0))').each(function () {
line.push(_quote_text(_trim_text($(this).text())));
});
lines.push(line.splice(0).toString());
})
$(tb).find('tbody>tr').each(function () {
let line = [];
$(this).find('td').each(function () {
if($(this).find('select').length){
line.push(_quote_text($(this).find('option:selected').val()));
}else if($(this).find('input').length){
line.push(_quote_text($(this).find('input').val()));
}
else
line.push(_quote_text(_trim_text($(this).text())));
});
lines.push(line.splice(0).toString());
})
output = lines.join('\n');
return output;
};
$.fn.table2csv = function () {
let csv = convert(this);
//cases = $('#out').append($("<pre>").text(csv));
return csv;
};
})(jQuery);
It seems you are you some jQuery plugin to convert table data to csv. It doesn't actually create file on you disk. When you are making the ajax POST request to server you are sending the form data. On the server side you have clicked = request.form['data'] here clicked is not the file. But your pandas read_csv expects the url or buffer type. You can get around this issue with StringIO.
#app.route('/update_file', methods=['GET', 'POST'])
#login_required
def update_file():
'''Opens the filtered_file page but with updated file'''
clicked = None
if request.method == 'POST':
clicked = StringIO(request.form['data'])
file_to_filter = pd.read_csv(clicked, sep=';', engine='python', encoding='utf_8_sig')
table1 = update_csv(file_to_filter)
table2 = table1.to_html(classes='my_class" id = "my_id')
return render_template('3_filtered_file.html', data=table2)

Django: How to save mxGraph, so when user refreshes the graph stays? (asynchronous)

I convert the current mxGraph the user creates into XML which is stored in the database (ajax.js). I return this in my views as a JSONResponse to my ajax request (views.py).
The data stored in the database saves, as I have checked in the Django administration page and the xml gets updated per save button.
This is all working fine, however the issue is that when I refresh the page the graph created does not stay on the page.
ajax.js
var button = mxUtils.button('Save', function()
{
//var url = "{%url'login'%}"
//var url = "{% url 'myapp:productdetail' %}";
//location.href = '/saveData/'
var encoder = new mxCodec();
var node = encoder.encode(graph.getModel());
var xml = mxUtils.getPrettyXml(node);
var csrftoken = getCookie('csrftoken');
$.ajax({
type: "POST",
url: "/saveData/",
data: { "xml": xml},
headers:{
"X-CSRFToken": csrftoken
},
success: function(data){
//console.log("data" + data[0])
//console.log(graph)
//var xmlDoc = data[0]
var xmlDoc = mxUtils.parseXml(data[0]);
//var xmlDoc = mxUtils.load("/saveData/").getXml();
//console.log("xmlDoc " + xmlDoc)
var node = xmlDoc.documentElement;
//console.log("node " + node)
var dec = new mxCodec(node.ownerDocument);
//console.log("dec " + dec)
//console.log("graph model " + graph.getModel())
dec.decode(node, graph.getModel());
}
});
views.py
def saveData(request, user):
if request.method == "POST":
#Get user profile
member = Member.objects.get(username=user)
#Get XML data once user presses save
#xmlData = request.POST['xml']
member.data = request.POST['xml']
member.save()
print(member.data)
response = JsonResponse([
member.data
], safe = False);
#return render(request, 'fastcookapp/index.html', {"xmlData": member.data})
return HttpResponse(response, content_type="application/json")
return HttpResponse('POST is not used')
models.py
class Member(User):
data = models.TextField(null=True)
def __str__(self):
return self.username
P.S I have no clue why my JS is not coming in colour, I have added the javascript tag and it's not working... sorry in advance
I had to create an Ajax GET request and decode the mxGraph as done above.

i need to parse json file in 10 files interval

i am getting json data from a files and create another json files in each loop and send request for that json files here is my code for creating json files
var derivatedFeatures = ["RMS","sb2xMagnitudev_ipspeak", "sbSubsynchronousv_ipspeak", "PeakPeak_mil", "sbHighFrequency_grms", "TruePeak_ips", "PeakPeak_g", "sb1xMagnitudev_ipspeak","Crestfactor"];
$.each(derivatedFeatures,function(index,feature){
$.each(data,function(index,item){
var featurefile ="Lines_"+feature+'_'+item['Line']+'_'+item['Component'].split(" ").join("_")+'.json'
filedata = {
file:featurefile,
site:item['Site'],
area:item['Area'],
line:item['Line'],
equipment:item['Equipment'],
component:item['Component'],
feature:feature
};
frank.sendAjax('/static/data/json/'+featurefile,'', 'GET', anomaliesDataAppend,filedata);
});
});
i want to load 10 files first
after page scroll i want to load 10 more
and processes continue
Reason for doing this
page stuck while loading all of json files and processing its data
i have 2000+ json files
i hope this help you:
here is i coded for your solution
$.each(derivatedFeatures,function(index,feature){
$.each(data,function(index,item){
indexnum++;
var featurefile ="Lines_"+feature+'_'+item['Line']+'_'+item['Component'].split(" ").join("_")+'.json'
filedata.push({file:featurefile,
site:item['Site'],
area:item['Area'],
line:item['Line'],
equipment:item['Equipment'],
component:item['Component'],
feature:feature,
indexnum:indexnum
});
});
});
loadFeatureFiles(filedata,0);
var loadFeatureFiles = function(filedata,indexnum){
var startfrom=indexnum;
var endto=startfrom+10;
for (var i=startfrom;i <= endto;i++) {
requestdata={filedata:filedata[i],indexnum:i};
frank.sendAjax('/static/data/json/'+filedata[i]['file'],'', 'GET', anomaliesDataAppend,requestdata);
};
};
assign data= rows and get when user scroll down and pass in the function
//data is induxnum
loadFeatureFiles(filedata,data);

convert image from base64 to image and save in database in django

I'm trying export a string base64 that represents an image taken from canvas html5, this is the code in javascript:
var canvas1 = $("#canvas1")[0];
var ctx1 = canvas1.getContext('2d');
dataURL1 = canvas1.toDataURL();
Whit ajax I sent the image to server:
$.ajax({
type: "POST",
url: "/regiter_respuesta_agilidad/",
data:{
'imagen1': dataURL1,
}
});
In views.py of django I use base64.b64decode to export the string to image:
imagen1 = request.POST['imagen1']
image_data = base64.b64decode(imagen1)
imagene = ContentFile(image_data, 'imagen1.png')
answer = Answer(imagen=imagene)
In models.py I have:
class Answer(models.Model):
imagen = models.ImageField(upload_to=url)
The Problem is when the image is saved, the file imagen1.png is corrupted and I can't open it, Can someone help me with this problem?, or is there another way to do this? thank you very much.
I'm guessing you need to strip the data: off the Data URI returned by canvas.toDataURL();.
A quick google search found some code designed for parsing data uris in python https://gist.github.com/zacharyvoase/5538178 and another: dataurl.py
instead of this line: image_data = base64.b64decode(imagen1)
use this line : image_data = base64.b64decode(imagen1[22:] + b'=' * (-len(imagen1[22:]) % 4))

Categories

Resources