Как загрузить файл и заполнить части сайта его содержимым? - PullRequest
0 голосов
/ 19 мая 2018

Есть похожие вопросы здесь и здесь , но они не решают мою проблему.

Допустим, у меня есть файл testdata.csv вот так:

A,B
1,3
2,4

и я хочу, чтобы пользователь разрешил загрузить файл, а затем - просто для простоты - отобразить его содержимое на той же странице, не затрагивая другие элементы на этой странице.Таким образом, мой желаемый результат будет выглядеть так:

enter image description here

Как бы я это сделал?Я нашел пару подходов, которые используют form для загрузки файла и отправки его (измененного) содержимого обратно (например, для его загрузки), но я изо всех сил пытаюсь найти решение для передачи ответа JSON обратно для изменения страницы (здесь: добавьте таблицу).

Это весь мой код:

from flask import Flask, render_template, request, jsonify
import pandas as pd
import numpy as np
import json

# Initialize the Flask application
app = Flask(__name__)


@app.route('/')
def index():
    return render_template('index.html')


@app.route('/_get_table', methods=["POST", "GET"])
def get_table():

    # how to catch the file here and send its content back?
    # file = ????
    # print(file)
    df = pd.DataFrame({"A": [1, 2], "B": [3, 4]})

    return jsonify(my_table=json.loads(df.to_json(orient="split"))["data"],
                   columns=[{"title": str(col)} for col in json.loads(df.to_json(orient="split"))["columns"]])

    # if I use a form, I can use
    # file = request.files['myfile']
    # however, how do I then send the JSON response?

if __name__ == '__main__':
    app.run(debug=True)

и мой index.html файл:

<!DOCTYPE html>
<html lang="en">
  <head>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
    <link href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet">
  </head>
  <body>
    <div class="container">
      <div class="header">
        <h3 class="text-center text-muted">Some great stuff</h3>
      </div>

      <hr class="mb-4">

      <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><br><br>

      <button class="btn btn-primary" type="button" id="upload_document">Upload and process!</button>

      <hr class="mb-4">

      <table id="pretty_table" class="table table-striped"></table>

      <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
      <script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js" type="text/javascript"></script>
      <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
      <script type="text/javascript">
        $(document).ready(function() {

          var table = null;
          $('#upload_document').bind('click', function() {

            $.getJSON('/_get_table', {
              // what to pass here?
            }, function(data) {

              if (table !== null) {
                table.destroy();
                table = null;
                $("#pretty_table").empty();
              }
              table = $("#pretty_table").DataTable({
                data: data.my_table,
                columns: data.columns

              });
            });
            return false;
          });

          $('.custom-file-input').on('change', function() {
             let fileName = $(this).val().split('\\').pop();
             $(this).next('.custom-file-label').addClass("selected").html(fileName);
          });
        });
      </script>
  </body>
</html>

1 Ответ

0 голосов
/ 20 мая 2018

@ charlietfl в комментариях и эта ссылка вывели меня на правильный путь.Можно использовать FormData, а затем .ajax вызов для достижения желаемого результата.Таким образом, важными частями ссылки выше (полные файлы можно найти ниже):

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

и

// Get form
var form = $('#fileUploadForm')[0];

// Create an FormData object
var data = new FormData(form);

и

$.ajax({
        type: "POST",
        enctype: 'multipart/form-data',
        url: "/_get_table",
        data: data,
        processData: false,

processData: false, важно, чтобы форма jQuery не преобразовывала данные в строку запроса, как описано в ссылке выше.

На сайте фляги мы можем легко получить файл, выполнив:

file = request.files['myfile']

df = pd.read_csv(file)

который превращает .csv в кадр данных панд.Очевидно, что перед этим должны быть проверки и т. Д.

Вся HTML страница index_formdata.html будет выглядеть следующим образом:

<!DOCTYPE html>
<html lang="en">
  <head>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
    <link href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet">
  </head>
  <body>
    <div class="container">
      <div class="header">
        <h3 class="text-center text-muted">Some great stuff</h3>
      </div>

      <hr class="mb-4">
      <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><br><br>

      <button class="btn btn-primary" type="button" id="upload_document">Upload and process!</button>

      <hr class="mb-4">

      <table id="pretty_table" class="table table-striped"></table>

      <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
      <script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js" type="text/javascript"></script>
      <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
      <script type="text/javascript">
        $(document).ready(function () {

            var table = null;

            $("#upload_document").click(function (event) {

                //stop submit the form, we will post it manually.
                event.preventDefault();

                // Get form
                var form = $('#fileUploadForm')[0];

                // Create an FormData object
                var data = new FormData(form);

                // disabled the submit button
                $("#upload_document").prop("disabled", true);

                $.ajax({
                    type: "POST",
                    enctype: 'multipart/form-data',
                    url: "/_get_table",
                    data: data,
                    processData: false,
                    contentType: false,
                    cache: false,
                    timeout: 600000,
                    success: function (data) {

                      if (table !== null) {
                        table.destroy();
                        table = null;
                        $("#pretty_table").empty();
                      }
                      table = $("#pretty_table").DataTable({
                        data: data.my_table,
                        columns: data.columns

                      });
                      $("#upload_document").prop("disabled", false);

                    },
                    error: function (e) {

                        alert(e.responseText);
                        console.log("ERROR : ", e);
                        $("#upload_document").prop("disabled", false);

                    }
                });

            });
            $('.custom-file-input').on('change', function() {
               let fileName = $(this).val().split('\\').pop();
               $(this).next('.custom-file-label').addClass("selected").html(fileName);
            });

        });
      </script>
  </body>
</html>

файл фляги следующим образом:

from flask import Flask, render_template, request, jsonify
import pandas as pd
import numpy as np
import json

# Initialize the Flask application
app = Flask(__name__)


@app.route('/')
def index():
    return render_template('index_formdata.html')


@app.route('/_get_table', methods=["POST", "GET"])
def get_table():

    # catch file from the form; if you have several files, just make several requests (access by name)
    file = request.files['myfile']

    df = pd.read_csv(file)

    return jsonify(my_table=json.loads(df.to_json(orient="split"))["data"],
                   columns=[{"title": str(col)} for col in json.loads(df.to_json(orient="split"))["columns"]])

if __name__ == '__main__':
    app.run(debug=True)

и testdata.csv файл

A,B,C
1,3,123
2,4,456
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...