我最初在单个网页上有一个长 Flask 表单,但现在我想将该表单分解为更小的块,并使用分页按钮迭代这些块。我只是对如何处理这个问题有点困惑。
到目前为止,我已经为这些不同的“块”创建了单独的表单类和 html 模板,但我不确定如何在主 app.py 脚本中将它们连接在一起。我本来打算采用动态路由方法,但我认为我做得不对。有什么建议吗?
表格类:
from flask_wtf import FlaskForm
from wtforms import StringField, TextField, SubmitField, IntegerField, SelectField, validators
class InputForm1(FlaskForm):
stack_name = StringField('STACK NAME', validators=[validators.required()])
resource_cfn_tmpl_deploy_bucket = SelectField('PIPELINE DEPLOYMENT BUCKET', validators=[validators.required()])
key_pair = SelectField('KEY PAIR', validators=[validators.required()])
start_point = SelectField('START POINT', validators=[validators.required()], choices=[("", "---"), ("", "fastq"), ("", "bam"), ("", "hdof"), ("", "gvcf"), ("", "vcf")])
qc = SelectField('QC', choices=[("", "---"), ("","BAM"), ("","VCF")])
class InputForm2(FlaskForm):
input_uri = StringField('INPUT BUCKET', validators=[validators.required()])
output_uri = StringField('OUTPUT BUCKET', validators=[validators.required()])
ref_uri = SelectField('REFERENCE BUCKET', validators=[validators.required()])
user_assets_uri = StringField('USER ASSETS BUCKET', validators=[validators.required()])
class InputForm3(FlaskForm):
target = StringField('TARGET')
package_name = StringField('PACKAGE NAME', validators=[validators.required()])
license_name = StringField('LICENSE NAME', validators=[validators.required()])
class InputForm4(FlaskForm):
cohort_prefix = StringField('COHORT PREFIX', validators=[validators.required()])
build = SelectField('BUILD', validators=[validators.required()], choices=[("", "---"), ("","GRCh38"), ("","GRCh37")])
ome = SelectField('OME', validators=[validators.required()], choices=[("", "---"), ("", "wgs"), ("", "wes")])
class InputForm5(FlaskForm):
cloudspan_mode = SelectField('CLOUDSPAN MODE', choices=[("", "---"), ("", "validation"), ("", "qc")])
project_id = StringField('PROJECT ID')
zone = StringField('ZONE')
cloud_file = StringField('CLOUD FILE')
submit_final = SubmitField('Execute Pipeline')
pipeline_1.html:(我还有 pipeline_2.....pipeline_5.html,具有上面 Form 类中定义的不同输入)
{% extends 'layout.html' %}
{% block body %}
<div class="content-section">
<form method="POST" action="">
{{ form.hidden_tag() }}
<fieldset class="form-group">
<br><br><br>
<legend class="border-bottom mb-4">Pipeline Input</legend>
<div class="form-group required">
{{ form.stack_name.label(class="form-control-label")}}
{{ form.stack_name(class="form-control form-control-lg") }}
</div>
<div class="form-group required">
{{form.resource_cfn_tmpl_deploy_bucket.label(class="form-control-label") }}
form.resource_cfn_tmpl_deploy_bucket(class="form-control form-control-lg") }}
</div>
<div class="form-group required">
{{ form.key_pair.label(class="form-control-label") }}
{{ form.key_pair(class="form-control form-control-lg") }}
</div>
<div class="form-group required">
{{ form.start_point.label(class="form-control-label") }}
{{ form.start_point(class="form-control form-control-lg") }}
</div>
<div class="form-group">
{{ form.qc.label(class="form-control-label") }}
{{ form.qc(class="form-control form-control-lg") }}
</div>
<nav aria-label="Page navigation example">
<ul class="pagination">
<li class="page-item"><a class="page-link" href=href="#" tabindex="-1">Previous</a></li>
<li class="page-item"><a class="page-link" href="{{ url_for('/1') }}">1</a></li>
<li class="page-item"><a class="page-link" href="{{ url_for('/2') }}">2</a></li>
<li class="page-item"><a class="page-link" href="{{ url_for('/3') }}">3</a></li>
<li class="page-item"><a class="page-link" href="{{ url_for('/4') }}">4</a></li>
<li class="page-item"><a class="page-link" href="{{ url_for('/5') }}">5</a></li>
<li class="page-item"><a class="page-link" href="#">Next</a></li>
</ul>
</nav>
</div>
</fieldset>
</div class="form-group">
</div>
</form>
<p>{{ error }}</p>
</div>
{% endblock %}
app.py:(当前尝试,我知道这是不正确的,但这就是我陷入困境的地方)
# Import the Flask app
from flask import Flask, url_for, render_template, request, flash, redirect
from math import ceil
from datetime import datetime
from user_input import InputForm1, InputForm2, InputForm3, InputForm4, InputForm5
import json
import subprocess
import os
import sys
import boto3
app = Flask('pipeline-ui')
app.config['S3_CLIENT'] = boto3.client('s3')
app.config['EC2_CLIENT'] = boto3.client('ec2')
app.debug = True
@app.route('/<page_num>', methods=['GET', 'POST'])
def pipeline(page_num):
if request.method == "POST":
if page_num == 1:
form = InputForm1(request.form)
return redirect('/2')
if page_num == 2:
form = InputForm2(request.form)
return redirect('/3')
if page_num == 3:
form = InputForm3(request.form)
return redirect('/4')
if page_num == 4:
form = InputForm4(request.form)
return redirect('/5')
if page_num == 5:
form = InputForm5(request.form)
return redirect('results')
return render_template('pipeline_{}.html'.format(page_num), title='Pipeline Input', form=form)
请记住,请求之间没有状态,因此,在其他一切正确的情况下,您需要一种方法来存储下一个步骤的每个步骤的数据。
如果您无法将每个步骤的数据存储在数据库中,您可以考虑重新排序表单,以便每个步骤都可以作为对数据库的提交有意义。
如果您不使用数据库(或文件),或者在完成所有步骤之前无法发送数据,那么另一种选择是将每个步骤的数据存储到下一个步骤中的隐藏输入中。
class StepForm(FlaskForm):
previous_field = SomeField(widget=HiddenInput())
# ...
step = StepForm()
step.previous_field.data = previous_step.field.data
当然,您也可以使用 javascript 在前端进行分页,并在最后在单个请求中完全发送所有数据。
我遇到了类似的问题,最终使用 JavaScript 在客户端解决了这个问题:https://uublog.de/simple-pagination-in-wtforms/