HTML表中同一表单类的多个WTForm字段?

时间:2014-02-16 08:43:54

标签: python flask wtforms

我正在努力弄清楚如何完成与表中另一个元素相关联的唯一表单字段实例。对于一个人为的例子,这里是以下代码:

from flask import Flask, render_template, request
from flask.ext.wtf import Form
from wtforms import TextField, BooleanField

app = Flask(__name__)

app.debug = True
app.config['SECRET_KEY'] = 'secret'

class Person(Form):
    fname = TextField('First Name')
    phone = TextField('Phone Number')
    email = TextField('Email Address')
    active = BooleanField('Active')

@app.route("/", methods=['GET', 'POST'])
def guest():
    names = ['Bob', 'Joe', 'Jason', 'John'] # this could be a list, or data returned from a db query, previous POST data, or whatever
    form = Person()
    if request.method == 'POST' and form.validate_on_submit():
        return str(form.data)

    return render_template('index.html', names=names, form=form)

if __name__ == "__main__":
    app.run(host='0.0.0.0')

我的模板:

<html>
<body>
<form action="" method="post">
<table border="1">
    <thead>
        <tr>
            <th>Name</th>
            <th>Telephone Number</th>
            <th>Email Address</th>
            <th>Active</th>
        </tr>
    </thead>
    <tbody>
        {% for n in names %}
        <tr>
            <td>{{ n }}</td>
            <td>{{ form.phone }}</td>
            <td>{{ form.email }}</td>
            <td>{{ form.active }}</td>
        </tr>
        {% endfor %}
    </tbody>
</table>

很明显,在HTML中,每个表行中每个输入元素的name参数都是相同的,因为正在使用相同的表单字段,因此在“POST”中,如果输入一个电话号码,现在为表中的所有名称行填充该电话号码。 “激活”复选框也是如此。我也尝试生成一个表单实例列表并将该列表传递给模板,但它似乎没有像我预期的那样工作。看起来我现在的选择是:

  1. 请勿使用WTForms(请参阅下面的注释)
  2. 使用WTForms FieldList + FormField(我认为这不会起作用,因为这些需要命名键和任意键,所以我遇到了完全相同的问题。)
  3. 以某种方式使用HiddenFields(甚至没想过这会如何工作)。
  4. 我知道我可以通过模板手动在表格中创建<input type>元素,并根据w为它们分配不同的名称/ ID,但这不是非常惯用的,加上我必须自己编写验证代码。

1 个答案:

答案 0 :(得分:2)

您通常会传入一个包含表单数据的多dict对象作为表单的第一个参数:

form = UpdateWidgetForm(request.form)

这确实要求POST数据与表单中的小部件匹配;每个小部件都会检查多个dict,并使用一些预先填充的数据提取它需要渲染的内容。

或者,您可以将值作为关键字参数传递,但这确实需要您自己验证输入,将任何值转换为正确的类型:

number = request.form.get('widget_number')
try:
    number = int(number)
except ValueError:
    abort(404)
policy = request.form.get('widget_policy')
if policy not in ('foo', 'bar'):
    abort(404)

form = UpdateWidgetForm(widget_number=number, widget_policy=policy)

请参阅文档中的How Forms get data

如果您需要在页面中生成多个表单,每个表单都是唯一的,来自同一表单对象,您需要为每个表单分配一个带有Form(prefix=..)参数的唯一前缀。