假设我有一个testdata.csv
这样的文件:
A,B
1,3
2,4
我希望用户允许上传文件然后 - 只是为了简单 - 在同一页面上显示其内容而不影响此页面上的任何其他元素。所以我期望的结果看起来像这样:
我该怎么做?我发现了一些使用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>
答案 0 :(得分:0)
@charlietfl和this link让我走上正轨。可以使用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
转换为pandas数据帧。显然,在执行此操作之前应该进行检查等。
整个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