I have a API in flask. The objetive is to receive a converted csv file (function in javascript) and form data in flask separate. Form data is metadata and csv file converted to json is data. I'm only getting the form data, the json file i'm getting none.
My json converted from csv file it's store in variable result and form data is stored in formdata. I send the two variable separated. I'm receiving all the data that i insert in HTML. The JSON that result from a function that convert csv files to json i'm not getting in flask side.
HTML
<!DOCTYPE html>
<html lang="PT">
<head>
<meta charset="utf-8">
<title>Register</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="/static/sendform.js"> </script>
<link href="{{url_for('static', filename='css/mainpage.css')}}" rel="stylesheet" type="text/css">
</head>
<body>
<div id="upper_left"></div>
<div id="upper_right"></div>
<div id="lower_left"></div>
<div id="lower_right"></div>
<div >
<div >Metadados - Dados relacionados com o Atleta</div>
<form action="index" method="post">
<div >
<div >
<span >Nome Completo</span>
<input type="text" name="fullName" placeholder="Introduza o nome completo do atleta">
</div>
<div >
<span >Data de Nascimento</span>
<input type="text" name="birthdate" placeholder="Introduza a data de nascimento do atleta">
</div>
<div >
<span >Altura</span>
<input type="text" name="height" placeholder="Introduza a altura do atleta em cm">
</div>
<div >
<span >Peso</span>
<input type="text" name="weight" placeholder="Introduza o peso do atleta em kg">
</div>
<div >
<span >Tamanho da Piscina</span>
<input type="text" name="poolsize" placeholder="Introduza o tamanho da piscina">
</div>
<div >
<span >Modalidade</span>
<input type="text" name="modality" placeholder="Introduza a modalidade">
</div>
<div >
<span >Estilo(s) de Natação</span>
<input type="text" name="swimStyle" placeholder="Introduza o estilo(s) de natação">
</div>
<div >
<span >Género</span>
<select name="gender">
<option value ="gender">Selecionar genéro</option>
<option value ="masculino">Masculino</option>
<option value ="feminino">Feminino</option>
</select>
<div >
<span >Escalão Etário</span>
<select name="gender-title">
<option value ="gender-title">Select gender group</option>
<option value ="Escola_de_natacao">ESCOLA DE NATACAO</option>
<option value ="grupos_de_natacao_desportiva">GRUPOS DE FORMACAO DESPORTIVA</option>
<option value ="cadeteA">CADETES A</option>
<option value ="cadeteB">CADETES B</option>
<option value ="infatilB">INFANTIS B</option>
<option value ="infatilA">INFANTIS A</option>
<option value ="juvenilB">JUVENIS B</option>
<option value ="juvenilA">JUVENIS A</option>
<option value ="junior">JUNIORES</option>
<option value ="senior">SENIORES</option>
</select>
</div>
<div >Metadados Envio de dados</div>
<div >
<span >Utilizador Id</span>
<input type="text" name="userId" placeholder="Introduza o seu Id">
</div>
<div >
<span >Token</span>
<input type="text" name="token" placeholder="Introduza o token">
</div>
<p>Selecionar o ficheiro localmente:</p>
<input name="myFile" type="file" accept=".txt,.xlsx, .xls, .csv" >
<div >
<input type="submit" id="btn-post" value="Enviar dados" onclick="do_ajax();">
<div ></dix>
</div>
</div>
</form>
</div>
</body>
</html>
Javascript
function do_ajax() {
var input = document.querySelector('input').files;
if(!input.length){
alert("No file selected");
return;
}
var file = input[0];
var reader = new FileReader();
reader.onload = (function() {
return function(e) {
var fileData = e.target.result.trim().split('\n').map(row => row.split(','));
var HEADERS = ["time", "yaw", "pitch", "roll", "heading", "ax", "ay", "az", "gx", "gy", "gz", "mx", "my", "mz"];
const RESULT = {};
// Assign every heading to the result.
for (const HEADING of HEADERS) RESULT[HEADING] = [];
fileData.map(row =>
// Each row → each column, number of columns === number of headers
row.map((column, i) =>
RESULT[HEADERS[i]]
.push(Number(column))
));
console.log(RESULT);
};
})(file);
reader.readAsText(file);;
let fullName = document.getElementById('fullName').value;
let birthdate = document.getElementById('birthdate').value;
let height = document.getElementById('height').value;
let weight = document.getElementById('weight').value;
let poolsize = document.getElementById('poolsize').value;
let modality = document.getElementById('modality').value;
let swimStyle = document.getElementById('swimStyle').value;
var tel = document.getElementById('gender').value;
var sel = document.getElementById('gender-title').value;
console.log(sel.value);
const formdata = new FormData();
formdata.append("fullName", fullName)
formdata.append("birthdate",birthdate)
formdata.append("weight",weight)
formdata.append("height",height)
formdata.append("poolsize",poolsize)
formdata.append("modality",modality)
formdata.append("swimStyle",swimStyle)
formdata.append("gender",tel)
formdata.append("gender-title",sel)
var xhr = new XMLHttpRequest();
xhr.open('POST', '/index', true);
xhr.send(formdata);
xhr.send(JSON.stringify(RESULT));
};
FLASK
from flask import Flask, request, render_template
import pymongo
import json
app = Flask(__name__)
app.debug = True
@app.route('/', methods=['GET', 'POST'])
@app.route('/index', methods=['GET', 'POST'])
def index():
if request.method == "POST":
name = request.form["fullName"]
birthdate =request.form["birthdate"]
poolsize =request.form["poolsize"]
height =request.form["height"]
weight =request.form["weight"]
modality =request.form["modality"]
swimStyle =request.form["swimStyle"]
gender = request.form["gender"]
gender_title = request.form["gender-title"]
output = request.get_json()
print(output)
print (name,birthdate,poolsize,height,weight,modality,swimStyle)
alldata = { "sessionData": output,
"metadata":{ "birthdate": birthdate, "Name": name,
"Weight": height,"Pool_size":poolsize,
"Weight":weight,"Gender":gender,"Gender_title":gender_title,
"modality":modality, "swimStyle": swimStyle}}
return alldata,200
else:
return render_template('index.html')
if __name__ == "__main__":
app.run()
CodePudding user response:
A data transfer can only conform to one format. This formatting is either an encoding for a form or corresponds to JSON formatting.
You can still send the data within one request. Either you add the JSON-formatted data as a field to the form, or you convert the form data into a JSON structure.
With the first variant, it is necessary to read the JSON data manually on the server side. You can use the python json library for this. For the latter, the framework does this work.
A third option is to transfer the file within the form and simply read it on the server side.
Whichever option you choose, don't forget to validate the inputs.
In the following example, all form data is converted to JSON and sent to the server. I shortened the code a bit for clarity.
The version of adding JSON formatted data to the form data should be self-explanatory.
I think the best solution is to read the file server side.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Read CSV to JSON</title>
</head>
<body>
<form name="my-form" method="post" enctype="" enctype="multipart/form-data">
<input type="text" name="name" />
<!-- ... -->
<input type="file" name="csv" allow="text/csv" />
<input type="submit" />
</form>
<script type="text/javascript">
((uri) => {
function readCSV(file, delim=',') {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onerror = reject;
reader.onload = (evt) => {
resolve(evt.target.result.split(/\r\n|\n/).map(line => line.split(delim)));
};
reader.readAsText(file);
});
}
function serialize(formData) {
const data = {};
for (const [k, v] of formData) data[k] = v;
return data;
}
// Register a listener for submit events and suppress the default behavior of the form.
const form = document.querySelector('form[name="my-form"]');
form.addEventListener('submit', async evt => {
evt.preventDefault();
if(!evt.target.csv.files.length) {
alert('No file selected.');
return;
}
const file = evt.target.csv.files[0];
const formData = new FormData(evt.target);
formData.delete('csv');
// Conversion of the form data into an object.
const data = serialize(formData);
// Reading and converting the file into a list of objects.
// Adding the list to the previous object.
data['csv'] = await readCSV(file, ',')
.then(csv => {
const head = ['time', 'yaw', 'pitch', 'roll', 'heading', 'ax',
'ay', 'az', 'gx', 'gy', 'gz', 'mx', 'my', 'mz'];
return csv.map(row => {
let r = {};
row.forEach((col, i) => r[head[i]] = Number(col));
return r;
});
});
// Sending the JSON data to the server.
fetch(uri, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
}).then(resp => resp.json())
.then(data => console.log(data));
});
})({{ url_for('.data') | tojson }});
</script>
</body>
</html>
from flask import Flask
from flask import (
jsonify,
render_template,
request,
)
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/data', methods=['POST'])
def data():
data = request.json
print(data)
return jsonify(success=True)