【问题标题】:Multiple WTForms with Same Radio Field on Same Page同一页面上具有相同无线电字段的多个 WTForm
【发布时间】:2015-03-27 20:00:10
【问题描述】:

好的,我已经在网上、文档和源代码中四处查看,但我对这个问题一无所知。所以我正在开发一个带有 wtforms 和 bootstrap 的 Flask 项目,我需要在一个页面上多次显示相同的表单。具体来说,这种形式:

class ProblemForm(Form):
    def __init__(self, formdata=None, obj=None, prefix='', title="", **kwargs):
        super(self.__class__, self).__init__(formdata=None, obj=None, prefix='', **kwargs)
        self.title = title

    opts = RadioField("Possible Corrections")
    alias_of = StringField("Alias of")
    select_alias = BooleanField("select_alias")
    user_input = StringField("New Entry")
    select_uinput = BooleanField("select_uinput")

在控制器逻辑(见下文)中,我发现我可以创建一个 ProblemForm 实例数组,并从会话中已有的数据中为每个“问题”设置选项。

@blueprint.route("/clean/review/<int:start>-<int:end>", methods=["GET", "POST"])
@login_required
def cleaning(start, end):
    prob_forms = []
    for pif in xrange(start, end+1):
        pf = ProblemForm(request.form, title=session["problems"][pif][0])
        pf.opts.choices = [(pr, pr) for pr in session["problems"][pif][1]]+[('<null>', '<null>')]
        prob_forms.append(pf)
    if request.method == "POST":        
        pass
    return render_template("main/cleaning.html", forms=prob_forms, buttons=ControlButtons(), 
                           start=start, end=end)

令人沮丧的是,这几乎有效。当表格发布时 request.form.lists() 包含:[('select_uinput', [u'7']), ('user_input', [u'', u'', u'', u'', u'', u '', u'', u'']), ('select_alias', [u'2']), ('alias_of', [u'', u'Mike Rowe 的肮脏工作', u'', u '', u'', u'', u'', u'']), ('opts', [u'Paradise']), ('next', [u'Next'])]。我可以处理这个;在第 7 个表单上选中了一个复选框,在第 2 个表单上选中了另一个复选框,在第二个表单上,用户在“alias_of”框中键入了“Mike Rowe 的肮脏工作”,等等。

问题是名为“opts”的 RadioField。它似乎只保存用户按下的最后一个按钮。任何人都知道为什么会这样,或者我应该在哪里寻找更多信息?

这是模板,如果有用的话:

{% extends "layout.html" %}
{% block content %}
    <form action="{{ url_for('main.cleaning', start=start, end=end) }}" method="POST" enctype="multipart/form-data">
        {% for form in forms %}
        {% set outloop = loop %}
            <div class="well well-lg">
                <h3><em>{{ form.title }}</em>?</h3>
                <!-- Possible Master List entries -->
                <div class="btn-group" id="opts_{{outloop.index}}" role="group" data-toggle="buttons" aria-label="...">   
                   {% for opt in form.opts %}
                        {% if loop.first %}
                            <label class="btn btn-default active">                        
                        {% else %}
                            <label class="btn btn-default">
                        {% endif %}
                            {{ opt }} {{ opt.label.text }}
                        </label>
                   {% endfor %}
                </div><br />

                <!-- Alias input -->
                <div class="row">
                  <div class="col-lg-6">
                    <div class="input-group">
                      <span class="input-group-addon">
                        {{ form.select_alias(value=outloop.index) }} 
                      </span>
                      <span class="input-group-addon" id="basic-addon2">Alias of</span>
                      {{ form.alias_of(class_="form-control") }}
                    </div><!-- /input-group -->
                  </div><!-- /.col-lg-6 -->
                 </div> <!-- /row -->
                 <!-- END Alias input -->

                <!-- New Entry input -->
                <div class="row">
                  <div class="col-lg-6">
                    <div class="input-group">
                      <span class="input-group-addon">
                        {{ form.select_uinput(value=outloop.index) }} 
                      </span>
                      <span class="input-group-addon" id="basic-addon2">New Entry</span>
                      {{ form.user_input(placeholder=form.title, class_="form-control") }}
                    </div><!-- /input-group -->
                  </div><!-- /.col-lg-6 -->
                 </div> <!-- /row -->
                </div>
                <!-- END Alias input -->
        {% endfor %}
        {{ buttons.back() }} {{ buttons.next() }} {{ buttons.save() }}
    </form>
{% endblock %}

【问题讨论】:

    标签: python forms twitter-bootstrap flask flask-wtforms


    【解决方案1】:

    选项1:给每个表单实例its own prefix

    for pif in xrange(start, end+1):
        pf = ProblemForm(request.form, title=session["problems"][pif][0], prefix='problem-%d' % pif)
        # etc
    

    选项 2:或者,如果您使用 FormFields 的 FieldList 提供封闭表单,WTForms 可以为您生成前缀表单。

    class EnclosingForm(Form):
        problems = FieldList(FormField(ProblemForm))
    

    然后使用append_entry 在循环中添加子表单:

    form = EnclosingForm(request.form)
    for i, pif in enumerate(xrange(start, end+1)):
        if len(form.problems.entries) <= i:
            form.problems.append_entry({'title': session["problems"][pif][0]})
        # etc
    

    【讨论】:

    • 我尝试了您建议的 FieldList 解决方案,问题是 EnclosureForm.problems.data 不包含用户输入表单的任何数据。我认为问题在于 jinja2 模板已关闭。我尝试了不同的更改,包括使用 {{forms.problems()}} 来解决问题。但是,无论我尝试什么,我仍然会得到一个字典列表,无论输入什么,所有这些字典都包含 False 和 None 值。
    • 啊!这是问题: class ProblemForm(Form): def init__(self, formdata=None, obj=None, prefix='', title="", **kwargs): super(self.__class, self).__init__(formdata=None, obj=None, prefix='', **kwargs) @Crast 的方法添加的前缀被我草率的子类化弄乱了。故事的寓意:伙计们,小心子类!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-11
    • 2014-03-15
    • 2012-12-26
    • 1970-01-01
    相关资源
    最近更新 更多