在烧瓶中接收 json 转换并形成数据

receive in flask json converted and form data

我有一个 API 装在烧瓶里。目标是接收转换后的 csv 文件(javascript 中的函数)并在 flask 中单独形成数据。表单数据是元数据,转换为 json 的 csv 文件是数据。 我只得到表单数据,json 文件我得到 none.

我的 json 从 csv 文件转换而来,它存储在变量结果中,表单数据存储在 formdata 中。我将两个变量分开发送。我收到了我在 HTML 中插入的所有数据。将 csv 文件转换为 json 的函数产生的 JSON 我没有进入 flask 端。

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 class="container">
      <div class="title">Metadados - Dados relacionados com o Atleta</div>   
      <form action="index" method="post">
        <div class="user-details">
          <div class="input-box">
            <span class="details">Nome Completo</span>
            <input type="text" name="fullName" placeholder="Introduza o nome completo do atleta">
          </div>
          <div class="input-box">
            <span class="details">Data de Nascimento</span>
            <input type="text" name="birthdate" placeholder="Introduza a data de nascimento do atleta">
          </div>
          <div class="input-box">
            <span class="details">Altura</span>
            <input type="text" name="height" placeholder="Introduza a altura do atleta em cm">
          </div>
          <div class="input-box">
            <span class="details">Peso</span>
            <input type="text" name="weight" placeholder="Introduza o peso do atleta em kg">
          </div>
          <div class="input-box">
            <span class="details">Tamanho da Piscina</span>
            <input type="text" name="poolsize" placeholder="Introduza o tamanho da piscina">
          </div>
          <div class="input-box">
            <span class="details">Modalidade</span>
            <input type="text" name="modality" placeholder="Introduza a modalidade">
          </div>
          <div class="input-box">
            <span class="details">Estilo(s) de Natação</span>
            <input type="text" name="swimStyle" placeholder="Introduza o estilo(s) de natação">
          </div>
          <div class="input-box">
            <span class="details">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 class="input-box">
            <span class="details">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 class="title">Metadados Envio de dados</div> 
          <div class="input-box">
            <span class="details">Utilizador Id</span>
            <input type="text" name="userId" placeholder="Introduza o seu Id">
          </div>
          <div class="input-box">
            <span class="details">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 class="button">            
            <input type="submit" id="btn-post" value="Enviar dados" onclick="do_ajax();"> 
            <div class="input-box"></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()

一次数据传输只能符合一种格式。此格式是表单的编码或对应于 JSON 格式。

您仍然可以在一个请求中发送数据。 您可以将 JSON-formatted 数据作为字段添加到表单中,或者将表单数据转换为 JSON 结构。

对于第一个变体,需要在服务器端手动读取 JSON 数据。您可以为此使用 python json 库。对于后者,框架会完成这项工作。
第三种选择是在表单中传输文件并在服务器端读取它。

无论您选择哪个选项,都不要忘记验证输入。

在下面的示例中,所有表单数据都被转换为JSON并发送到服务器。为了清楚起见,我稍微缩短了代码。
表单数据添加JSON格式数据的版本应该是self-explanatory.
我认为最好的解决方案是读取文件服务器端。

<!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)