КОНТЕКСТ
Я создал веб-приложение Flask, которое имеет форму на веб-странице, и затем я хочу, чтобы пользователь сразу увидел результаты этой формы справа от формы. Когда форма отправляется, сценарий python активируется на бэкэнде, и в результате получается HTML-файл результатов (authorList.html
), который я хочу отобразить рядом с формой.
ПРОБЛЕМА
Насколько я понимаю, это требует от меня использования Ajax, поэтому я могу получать результаты, не обновляя страницу, но я не так хорошо знаю, как передать этот файл результатов HTML из фляги app.py в шаблон HTML и затем добавьте это как узел к дереву DOM.
1) Мой код настроен до сих пор таким образом, что вызывается маршрут upload
, который затем отображает index.html
, а затем код JS там ссылается на маршрут results
, который затем отображает index.html
снова, передавая файл результатов HTML в виде строки. Я частично настроил шаг преобразования HTML-строки в DOM-элемент в index.html
, где он говорит <p>Results should display here.</p>
(так как это часть страницы, где я хочу отображать HTML-файл результатов), но я не уверен, что я на правильном пути и как приступить к выполнению приложения.
2) Кроме того, когда я пытаюсь запустить этот код ниже, чем он есть, я получаю ошибку JS Uncaught SyntaxError: Unexpected token ;
, указывающую на эту строку index.html
: var d = document.createElement('div'); d.innerHTML = ; return d.firstChild;
... это потому, что я не правильно передать переменную data
на стороне приложения 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>
UPDATE
Я попробовал следующее изменение в своем коде 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