javascript - 如何将 HTML 字符串从烧瓶应用程序传递到 HTML 模板作为 DOM 元素,然后 appendChild
问题描述
语境
我创建了一个在网页上有一个表单的 Flask Web 应用程序,然后我希望用户立即在表单的右侧看到该表单的结果。提交表单后,会在后端激活一个 python 脚本,这会生成一个 HTML 结果文件 ( authorList.html
) - 这是我想在表单旁边显示的内容。
问题
据我了解,这需要我使用 Ajax,所以我可以在不刷新页面的情况下获得结果,但我不熟悉如何将 HTML 结果文件从烧瓶 app.py 传递到 HTML 模板,然后追加作为 DOM 树的一个节点。
1)到目前为止,我已经设置了我的代码,以便upload
调用路由,然后渲染index.html
,然后其中的 JS 代码引用回results
路由,然后index.html
再次渲染,将 HTML 结果文件作为字符串传递。index.html
我已经在它所说的位置部分设置了 HTML 字符串到 DOM 元素的转换步骤<p>Results should display here.</p>
(因为这是我希望显示 HTML 结果文件的页面部分),但我不确定我是否在正确的轨道上以及如何继续进行 appendchild。
2)另外,当我尝试以下面的方式运行此代码时,我收到Uncaught SyntaxError: Unexpected token ;
指向以下行的JS 错误index.html
:var d = document.createElement('div'); d.innerHTML = ; return d.firstChild;
...是因为我没有在data
Flask 应用程序端正确传递变量吗?(相应地在代码中解决和更新)
(注意:我对JS不熟悉,所以如果这看起来很简单,我提前道歉!)
源代码
应用程序.py:
@app.route("/", methods=['GET', 'POST'])
def upload():
return render_template('index.html', template_file=app.config['TEMPLATE_FILE'])
@app.route("/results", methods=['POST'])
def results():
data = []
if request.method == 'POST':
if request.form['affiliation'] == "letter":
affiliation = "let"
elif request.form['affiliation'] == "number":
affiliation = "num"
proc = subprocess.Popen('python author_script.py {} -p {} -s {} -m {}'.format(file.filename, period, space, affiliation), shell=True, stdout=subprocess.PIPE)
while proc.poll() is None:
time.sleep(0.5)
# Convert resulting HTML file to a string and pass to index.html
with open('authorList.html') as f:
data.append("".join(f.readlines()))
return render_template('index.html', data=''.join(data))
索引.html:
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
$('form').submit(function (e) {
var url = "{{ url_for('results') }}";
$.ajax({
type: "POST",
url: url,
data: $('form').serialize(),
success: function (data) {
console.log(data)
}
});
e.preventDefault();
});
});
</script>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-sm-6">
<div>
<br>
<p>Download the template file below and re-upload with your custom author information:</p>
<a href="static/ExampleAuthorList.txt" download="Authors_Template.txt"><button type="button">Download</button></a><br><br>
<form action="" id="myform" method=post enctype=multipart/form-data>
<div id="buttonDiv">
<p><input type=file name=file value="Choose File">
<p>Mark affiliations with:</p>
<input type="radio" name="affiliation" value="number" id="number" class="form-radio" checked><label for="number">Number</label><br>
<input type="radio" name="affiliation" value="letter" id="letter" class="form-radio"><label for="letter">Letter</label>
<br><br>
</div>
<input type=submit value=Upload></p>
</form>
</div>
</div>
<div class="col-sm-6">
<div>
<p>Results should display here.</p>
<script>
var d = document.createElement('div'); d.innerHTML = "{{ data }}"; return d.firstChild;
# Need code for appending child
</script>
</div>
</div>
</div>
</div>
</body>
</html>
更新
我在我的 JS 代码中尝试了以下更改(在 中index.html
),但仍然没有看到任何结果出现在主页上。
<script>
var data
$(document).ready(function() {
$('form').submit(function (e) {
var url = "{{ url_for('results') }}"; // send the form data here.
$.ajax({
type: "POST",
url: url,
data: $('form').serialize(),
success: function (data) {
var d = document.createElement('div');
d.innerHTML = data;
$(".my-results").html(data);
}
});
e.preventDefault(); // block the traditional submission of the form.
});
});
</script>
.
.
.
.
<div>
<br>
<p class="my-results">Results should display here.</p>
</div>
</div>
更新 2:完整的 app.py
@app.route("/", methods=['GET', 'POST'])
def upload():
return render_template('index.html', template_file=app.config['TEMPLATE_FILE'])
@app.route("/results", methods=['GET', 'POST'])
def results():
if 'file' not in request.files:
flash('No file chosen', 'danger')
return redirect(request.url)
file = request.files['file']
if file.filename == '':
flash('No selected file', 'danger')
return redirect(request.url)
filename = secure_filename(file.filename)
if not allowed_file(file.filename):
flash('Incorrect file extension. Must be .TXT!', 'danger')
if places_exist(os.path.join(app.config['UPLOAD_FOLDER'], filename)) == False:
flash('There is an affiliation missing from your Place list. Please re-try.', 'danger')
return redirect(request.url)
else:
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
os.chdir('/Users/cdastmalchi/Desktop/author_script/')
if request.form['affiliation'] == "letter":
affiliation = "let"
elif request.form['affiliation'] == "number":
affiliation = "num"
if "Yes sep period" in request.form.getlist('period'):
period = "y"
else:
period = "n"
if "Yes sep space" in request.form.getlist('space'):
space = "y"
else:
space = "n"
proc = subprocess.Popen('python author_script.py {} -p {} -s {} -m {}'.format(file.filename, period, space, affiliation), shell=True, stdout=subprocess.PIPE)
# Wait until process terminates
while proc.poll() is None:
time.sleep(0.5)
with open("authorList.html") as f:
data = ''.join(f.readlines())
print(data)
return data
解决方案
要动态上传文件,您需要FormData
在 Javascript 中将对象与POST
请求一起使用。此解决方案发送两个单独的请求:POST
带有文件数据的GET
请求和带有附加值的请求。文件名存储在计算最终数据时flask.session
在请求的上下文中使用:GET
首先,在你的 中app.py
,你需要三个路由:一个渲染路由index.html
,一个处理文件数据的路由,最后,一个返回 html 的路由:
app.py
:
import flask, string, random
import json
app = flask.Flask(__name__)
app.secret_key = ''.join(random.choice(string.ascii_letters) for _ in range(20)) #needed to use flask.session
@app.route('/', methods=['GET'])
def home():
return flask.render_template('index.html')
@app.route('/process_file', methods=['POST'])
def process_file():
#here, you can run all the checks as before, but instead of flash, you can return jsonified results to read in the front-end
if 'file' not in flask.request.files or not flask.request.files['file'].filename:
return flask.jsonify({'result':'False', 'message':'no files selected'})
file = flask.request.files['file']
filename = secure_filename(file.filename)
if not allowed_file(file.filename):
return flask.jsonify({'result':'False', 'message':'Must be TXT file!'})
if not places_exist(os.path.join(app.config['UPLOAD_FOLDER'], filename)):
return flask.jsonify({'result':'False', 'message':'There is an affiliation missing from your Place list. Please re-try.'})
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
flask.session['filename'] = filename
return flask.jsonify({'result':'True'})
@app.route('/upload_vals')
def upload_vals():
payload = json.loads(flask.request.args.get('payload'))
#do something with payload
#payload will now be in the form:
#{'affiliation':'Number', 'period':'no', 'space':'yes'}
proc = subprocess.Popen('python author_script.py {} -p {} -s {} -m {}'.format(flask.session['filename'], 'y' if _checked['period'] else 'n', 'y' if _checked['space'] else 'n', aff[:3]), shell=True, stdout=subprocess.PIPE)
while proc.poll() is None:
time.sleep(0.5)
with open("authorList.html") as f:
data = ''.join(f.readlines())
return flask.jsonify({'data':data})
index.html
:
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
</head>
<body>
</body>
<div class='wrapper'>
<p>Download the template file below and re-upload with your custom author information:</p>
<a href="static/ExampleAuthorList.txt" download="Authors_Template.txt"><button type="button">Download</button></a><br><br>
<form action="" id="myform" method=post enctype=multipart/form-data>
<input type=file name=file value="Choose File">
<p class='error_message'></p>
</form>
<div id="buttonDiv">
<p>Mark affiliations with:</p>
<input type="radio" name="affiliation" value="number" data-key='affiliation' data-value='number' class="form-radio main_checkbox" checked><label for="number">Number</label><br>
<input type="radio" name="affiliation" value="letter" data-key='affiliation' data-value='letter' class="form-radio main_checkbox"><label for="letter">Letter</label><br>
<p>Separate initials with period:</p>
<input type="radio" name="period" value="separated" data-key='period' data-value='yes' class="form-radio period"><label for="period">Yes</label><br>
<input type="radio" name="period" data-key='period' data-value='no' value="separated" class="form-radio period" checked><label for="period">No</label>
<br>
<p>Separate initials with space:</p>
<input type="radio" name="space" value="separated" data-key='space' data-value='yes' class="form-radio spacing"><label for="space">Yes</label><br>
<input type="radio" name="space" data-key='space' data-value='no' value="separated" class="form-radio spacing" checked><label for="space">No</label><br>
<br><br>
</div>
<button class='submit_data'>Submit</button>
<div>
<br>
<p class="my-results"></p>
</div>
</div>
<script>
$(document).ready(function(){
$('.wrapper').on('click', '.submit_data', function(){
var form_data = new FormData($('#myform')[0]);
var flag = true;
$.ajax({
type: 'POST',
url: '/process_file',
data: form_data,
contentType: false,
cache: false,
processData: false,
success: function(data) {
if (data.result === 'False'){
$('.error_message').html(data.message)
flag = false;
}
},
});
if (flag){
var payload = {};
$('.form-radio').each(function(){
if ($(this).prop('checked')){
payload[$(this).data('key')] = $(this).data('value');
}
});
$.ajax({
url: "/upload_vals",
type: "get",
data: {'payload':JSON.stringify(payload)},
success: function(response) {
$(".my-results").html(response.data);
},
});
}
});
});
</script>
</html>
在您更新的 HTML 中,表单值和表单值的来源有点不清楚app.py
,period
但是space
,在index.html
上面,提供了两个额外的复选框来接收来自用户的值。
推荐阅读
- php - 如何在 PHP 中从此数组中获取文件扩展名
- windows-10 - 如何将自定义上下文菜单添加到特定类型的所有扩展(例如所有视频文件)
- performance - Flutter Pdf Viewer 性能
- javascript - Threebox 如何获取地图上的所有 3d 对象?
- sql - 加入两个表
- c++ - 自动填写 telnet 会话中的字段
- python - 如何使用 Matplotlib 增加条形图大小
- powerbi - Power Query - 循环提取分隔符之间的文本
- javascript - 使用 Visual Studio 2019 时如何在浏览器而不是控制台中运行 Javascript 程序
- mysql - 如何最好地刷新 EC2 中的暂存实例