问题
I'm using Flask and Flask-WTF and I need to create a form that contains several blocks (subforms) of a similar structure (like a subform with one SelectField and one TextAreaField). As the docs suggest, I can use FormField together with FieldList to achieve this goal. However, I need to tweak my SelectField's dynamically (changing their choices at runtime according to values in the database). The docs now suggest
Note that the choices keyword is only evaluated once, so if you want to make a dynamic drop-down list, you’ll want to assign the choices list to the field after instantiation.
One can find an example of this approach here. However, FormField is accepting form_class, not an instance (at least, according to the docs), so it seems that these two recipes do not play well together.
Are there any other ideas?
回答1:
Okay, it's easier than I thought. You have to create those subforms with empty choices, create list of them and then adjust choices inside the list items.
class UserForm(wtforms.Form):
# must inherit from wtforms.Form, not flask-WTForms'
# see http://stackoverflow.com/questions/15649027/wtforms-csrf-flask-fieldlist
first_name = StringField('First Name', [validators.DataRequired()])
last_name = StringField('Last Name', [validators.DataRequired()])
accepted_policy = BooleanField('Accept Policy')
experience = SelectField('Experience', coerce=int)
class UsersForm(Form):
users = FieldList(FormField(UserForm), min_entries=2)
@app.route('/', methods=['GET', 'POST'])
def hello_world():
form = UsersForm(users=[{}, {}, {}])
form.users[0].experience.choices=[(1, 'One'), (2, 'Two')]
form.users[1].experience.choices = [(1, 'Uno'), (2, 'Du')]
form.users[2].experience.choices = [(0, 'Zero')]
return render_template("hello.html", form=form)
And here is a template:
{% macro render_field(field) %}
<dt>{{ field.label }}
<dd>{{ field(**kwargs)|safe }}
{% if field.errors %}
<ul class=errors>
{% for error in field.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</dd>
{% endmacro %}
<form method=post>
<dl>
{{ form.hidden_tag()}}
{% for user_entry_form in form.users %}
{{ user_entry_form.name }}
{{ render_field(user_entry_form.first_name) }}
{{ render_field(user_entry_form.last_name) }}
{{ render_field(user_entry_form.experience) }}
{% endfor %}
</dl>
<p><input type=submit value=Go!>
</form>
来源:https://stackoverflow.com/questions/43159368/dynamically-adjusted-forms-inside-fieldlist