语境
我创建了一个Flask Web应用程序,该应用程序在网页上具有一个表单,然后希望用户立即在表单的右侧看到该表单的结果.提交表单后,将在后端激活python脚本,这将生成一个HTML结果文件(authorList.html)-这是我要在表单旁边显示的内容.
问题
据我了解,这要求我使用Ajax,因此我无需刷新页面即可获得结果,但是我不熟悉如何将该HTML结果文件从flask app.py传递到HTML模板,然后追加作为DOM树的节点.
1)到目前为止,我已经设置了代码,以便调用上载路由,然后呈现index.html,然后其中的JS代码返回结果路由,然后再次呈现index.html,并传入HTML结果文件作为字符串.我已经在index.html中部分设置了HTML字符串到DOM元素的转换步骤,在该步骤下,它说< p>结果应在此处显示. (因为这是我希望HTML结果文件显示在页面的一部分),但是不确定我是否走对了路以及如何继续执行appendchild.
2)另外,当我尝试按原样运行此代码时,我收到了JS错误Uncaught SyntaxError:Unexpected token;指向index.html的这一行:var d = document.createElement(‘div’); d.innerHTML =;返回d.firstChild; …是因为我没有在Flask应用程序端正确传递数据变量吗? (已通过代码重新解决和更新)
(注意:我对JS不熟悉,因此,如果这看起来很简单,我先向您道歉!)
源代码
app.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))
index.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",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("/",template_file=app.config['TEMPLATE_FILE'])
@app.route("/results",'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,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
首先,在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]),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>
在更新后的app.py中,还不太清楚句点和空格形式的值源自HTML,但是,在上面的index.html中,提供了两个附加的复选框来从用户那里接收该值.