代码之家  ›  专栏  ›  技术社区  ›  claudiadast

如何用“下一步”按钮对烧瓶窗体分页?

  •  0
  • claudiadast  · 技术社区  · 7 年前

    目前,使用Flask,我有一个主页,其中有一个供用户填写的(长)表单。不过,我想把这个表单分成几块,然后用“下一步”按钮反复浏览(有点像你在网上买东西,需要浏览不同的页面来填写你的信息)。到目前为止,我尝试了以下方法:

    在主页html中实现多个“提交”按钮:

    {% extends 'layout.html' %}
    
    {% block body %}
        <div class="content-section">
            <form method="POST" action="">
                {{ form.hidden_tag() }}
                <fieldset class="form-group">
                    <legend class="border-bottom mb-4">Pipeline Input</legend>
                    <div class="form-group required">
                        {{ form.stack_name.label(class="form-control-label") }}
                        {{ form.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>
                        {{ form.submit_1(class="btn btn-outline-info") }}
                    <div class="form-group required">
                        {{ form.input_uri.label(class="form-control-label") }}
                        {{ form.input_uri(class="form-control form-control-lg") }}
                    </div>
                    <div class="form-group required">
                        {{ form.output_uri.label(class="form-control-label") }}
                        {{ form.output_uri(class="form-control form-control-lg") }}
                    </div>
                    <div class="form-group required">
                        {{ form.ref_uri.label(class="form-control-label") }}
                        {{ form.ref_uri(class="form-control form-control-lg") }}
                    </div>
                    <div class="form-group required">
                        {{ form.user_assets_uri.label(class="form-control-label") }}
                        {{ form.user_assets_uri(class="form-control form-control-lg") }}
                    </div>
                        {{ form.submit_2(class="btn btn-outline-info") }}
                    <div class="form-group">
                        {{ form.target.label(class="form-control-label") }}
                        {{ form.target(class="form-control form-control-lg") }}
                    </div>
                    <div class="form-group required">
                        {{ form.package_name.label(class="form-control-label") }}
                        {{ form.package_name(class="form-control form-control-lg") }}
                    </div>
                    <div class="form-group required">
                        {{ form.license_name.label(class="form-control-label") }}
                        {{ form.license_name(class="form-control form-control-lg") }}
                    </div>
                    {{ form.submit_final(class="btn btn-outline-info") }}
                </div>
                </fieldset>
                </div class="form-group">
                </div>  
            </form>
            <p>{{ error }}</p>
        </div>
    
    {% endblock %}
    

    这里是定义表单输入的地方:

    from flask_wtf import FlaskForm
    from wtforms import StringField, TextField, SubmitField, IntegerField, SelectField, validators
    
    class InputForm(FlaskForm):
    
        stack_name = StringField('STACK NAME', validators=[validators.required()])
        deploy_bucket = SelectField('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")])
    
        submit_1 = SubmitField('Next')
    
        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()])
    
        submit_2 = SubmitField('Next')
    
        target = StringField('TARGET')
        package_name = StringField('PACKAGE NAME', validators=[validators.required()])
        license_name = StringField('LICENSE NAME', validators=[validators.required()])
    
        submit_final = SubmitField('Execute Pipeline')
    

    这是我的应用程序类型,其中处理表单数据。目前仍设置为只有一个提交按钮,因此我不确定如何处理“下一步”按钮/分页:

    @app.route('/', methods=['GET', 'POST'])
    def pipeline():
        form = InputForm(request.form)
        form.deploy_bucket.choices = [("", "---")] + [("", bucket["Name"]) for bucket in app.config['S3_CLIENT'].list_buckets()["Buckets"]]
        form.ref_uri.choices = [("", "---")] + [("", bucket["Name"]) for bucket in app.config['S3_CLIENT'].list_buckets()["Buckets"]]
        form.key_pair.choices = [("", "---")] + [("", pair["KeyName"]) for pair in app.config['EC2_CLIENT'].describe_key_pairs()["KeyPairs"]]
    
        if request.method == 'POST':
            STACK_NAME = form.stack_name.data
            DEPLOY_BUCKET = form.deploy_bucket.data
            KEY_PAIR = form.key_pair.data
            START_POINT = form.start_point.data
            QC = form.qc.data
            INPUT_URI = form.input_uri.data
            OUTPUT_URI = form.output_uri.data
            REF_URI = form.ref_uri.data
            USER_ASSETS_URI = form.user_assets_uri.data
            TARGET = form.target.data
            PACKAGE_NAME = form.package_name.data
            LICENSE_NAME = form.license_name.data
    
            flash('The pipeline has been executed!', 'success')
    
            dic = {
                    "STACK_NAME": STACK_NAME, 
                    "DEPLOY_BUCKET": DEPLOY_BUCKET,
                    "KEY_PAIR": KEY_PAIR,
                    "START_POINT": START_POINT,
                    "QC": QC,
                    "INPUT_URI": INPUT_URI,
                    "OUTPUT_URI": OUTPUT_URI,
                    "REF_URI": REF_URI,
                    "USER_ASSETS_URI": USER_ASSETS_URI,
                    "LOCAL_ASSETS_DIR": LOCAL_ASSETS_DIR,
                    "SAMPLE_FILE": SAMPLE_FILE,
                    "TARGET": TARGET,
                    "PACKAGE_NAME": PACKAGE_NAME,
                    "LICENSE_NAME": LICENSE_NAME,
                  }
    
            proc = subprocess.Popen('pwd', shell=True, stdout=subprocess.PIPE)
    
            with open("input.json", 'w') as f:
                json.dump(dic, f)
    
            proc = subprocess.Popen('python pipeline.py -p', shell=True, stdout=subprocess.PIPE)
    
            return redirect(url_for('dashboard'))
    
        return render_template('pipeline.html', title='Pipeline Input', form=form)
    
    @app.route('/dashboard')
    def dashboard():
        return render_template('dashboard.html')
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   nmg49    7 年前

    如果你坚持使用Flask来完成这个任务,最简单的方法就是把表单分成多个表单,也许是按类别。在处理一个表单之后,您的flask代码将重定向到下一个表单。

    然而,特别是在2018年,这可能应该在客户端而不是服务器端完成。原因是这里的问题实际上与负责处理表单的Flask无关,而是与负责显示表单的前端有关。

    优点很多。首先,您可以一次加载整个表单,但可以将每次显示的内容分块。这将允许您通过只提交一个表单来保持flask代码的简单性,但是您可以精确地控制向用户显示的内容。此外,您还减少了从客户端到服务器的往返次数,这将为用户提供更好的性能。

    如果您希望避免编写字体结束分页代码,那么有一些解决方案可以集成到表单中。我个人用过 Bootstrap's Pagination 取得巨大成功。

    推荐文章