gpt4 book ai didi

javascript - 如何将 HTML 字符串作为 DOM 元素从 Flask 应用程序传递到 HTML 模板,然后 appendChild

转载 作者:可可西里 更新时间:2023-11-01 13:19:01 24 4
gpt4 key购买 nike

语境

我创建了一个 Flask 网络应用程序,该应用程序在网页上有一个表单,然后我希望用户立即在表单右侧看到该表单的结果。提交表单后,后端会激活一个 python 脚本,这会生成一个 HTML 结果文件 ( authorList.html ) - 这就是我想在表单旁边显示的内容。

问题

据我所知,这需要我使用 Ajax,因此我可以在不刷新页面的情况下获得结果,但我不太熟悉如何将 HTML 结果文件从 flask 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) 另外,当我尝试按原样运行这段代码时,我得到一个 JS 错误 Uncaught SyntaxError: Unexpected token ;指向 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))

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

最佳答案

要动态上传文件,您需要使用 Javascript 中的 FormData 对象和 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>

在您更新的 app.py 中,periodspace 形式的值源自 HTML 的位置有点不清楚,但是,在上面的 index.html 中,提供了两个额外的复选框来接收来自用户的这个值。

关于javascript - 如何将 HTML 字符串作为 DOM 元素从 Flask 应用程序传递到 HTML 模板,然后 appendChild,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55818897/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com