当尝试使用WTForms设置SelectField的默认值时,我将值传递给'default'参数,如此。
class TestForm(Form):
test_field = SelectField("Test: ", choices=[(1, "Abc"), (2, "Def")], default=2)
我也尝试了以下内容。
class TestForm(Form):
test_field = SelectField("Test: ", choices=[(1, "Abc"), (2, "Def")], default=(2, "Def"))
既不将默认的选定字段设置为“Def”。这适用于其他类型的字段,如TextField。如何设置SelectField的默认值?'
答案 0 :(得分:33)
我认为这个问题是由Field
的{{1}}属性覆盖data
而导致WTForms不理解的东西(例如数据库模型对象 - 它期望一个default
)。如果你在构造函数中填充了表单,就会发生这种情况:
int
解决方案是在填充表单后手动设置form = PostForm(obj=post)
属性:
data
答案 1 :(得分:26)
您发布的第一种方式是正确的,它对我有用。对它不起作用的唯一解释是,你运行的是旧版本的WTForms,它在1.0.1上为我工作
答案 2 :(得分:14)
有几种方法可以做到这一点。您的第一个代码段确实是正确的。
如果您想在动态视图中执行此操作,您还可以执行以下操作:
form = TestForm()
form.test_field.default = some_default_id
form.process()
答案 3 :(得分:11)
Flask-WTF 0.14.2
用户在这里。所以这个答案适用于任何与我有类似问题的人。
基本上,以前的解决方案都没有与form.validate_on_submit()
正常运行。
设置form.test_field.data
确实会在加载页面时更改默认值,但在validate_on_submit
之后数据保持不变(浏览器中的用户更改无效)。
设置form.test_field.default
然后调用form.process()
也会在页面加载时更改值,但validate_on_submit
将失败。
以下是新方法:
class TestForm(Form):
test_field = SelectField("Test", choices=[(0, "test0"), (1, "test1")])
@app.route("/test")
def view_function():
form = TestForm(test_field=1)
if form.validate_on_submit():
...
答案 4 :(得分:6)
当您使用choices
时,这是[{1}}设置SelectField
,其工作方式如下:
int
或:
test_select = SelectField("Test", coerce=int, choices=[(0, "test0"), (1, "test1")], default=1)
答案 5 :(得分:0)
如果您使用flask_wtf,并且想为嵌套在这样的FieldList中的不同SelectField设置默认值
from flask_wtf import FlaskForm
class FormWithSelect(FlaskForm):
my_select_field = SelectField(validators=[DataRequired()], coerce=int)
class FormWithMultipleSelects(FlaskForm):
select_fields = FieldList(FormField(FormWithSelect), min_entries=1)
submit = SubmitField(label="save all the select field values")
解决方案是覆盖data
,而不是您期望的default
。
def generate_my_form(my_data, overwrite_data=True):
form = FormWithMultipleSelects(select_fields=[{
"my_select_field": {
"name": d["name"],
# ...
}
} for d in my_data]))
for n range(len(form.select_fields)):
form.select_fields[n].my_select_field.choices = [(1,'foo'), (2,'bar')]
# I wan't 'bar' to be the option selected by default
# form.select_fields[n].my_select_field.default = 2 # has no effect!
if overwrite_data:
form.select_fields[n].my_select_field.data = 2 # works
基本上,此解决方案与上面的Elliots answer类似;我只是想为FieldList的更复杂情况提供解决方案。 nikitz在评论中提到有副作用:form.validate_on_submit()
在覆盖data
时不起作用!您可以构建一个简单的解决方法,在调用data
时禁止覆盖validate_on_submit()
。
form_for_validation = generate_my_form(my_data, False)
if form_for_validation.validate_on_submit():
# do something with form_for_validation.data
else:
form_with_default_data = generate_my_form(my_data, True)
render_template(..., form=form_with_default_data)
它不是超级优雅,但可以。
PS:我的声誉太低,无法直接对Elliot的正确答案发表评论。
答案 6 :(得分:0)
我认为动态设置默认选择字段有些问题,我认为这很有用。 该模型是这样的:
a
表单是这样的:
class State(db.Model):
__tablename__ = 'states'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(128), nullable=False)
class City(db.Model):
__tablename__ = 'cities'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64))
state_id = db.Column(db.Integer, db.ForeignKey('states.id'))
state = db.relationship(State, backref='state')
class User(UserMixin, db.Model):
...
city_id = db.Column(db.Integer, db.ForeignKey('cities.id'))
city = db.relationship('City', backref='city')
视图是这样的:
class UserEditForm(FlaskForm):
...
state = SelectField("state", coerce=int)
city = SelectField("city", coerce=int)
....
def __init__(self, state_id, *args, **kwargs):
super(UserEditForm, self).__init__(*args, **kwargs)
self.state.choices = [(state.id, state.name)
for state in State.query.order_by('name').all()]
self.city.choices = [(city.id, city.name)
for city in City.query.filter_by(state_id=state_id).order_by('name').all()]
效果很好,并正确设置了Selectfield默认值。但我更改了这样的代码:
视图中:
@dashboard.route('/useredit', methods=['GET', 'POST'])
@login_required
def useredit():
....
user = current_user._get_current_object()
form = OrganEditForm(state_id=user.city.state_id, state=user.city.state_id, city=user.city_id)
....
表格
@dashboard.route('/useredit', methods=['GET', 'POST'])
@login_required
def useredit():
....
user = current_user._get_current_object()
form = OrganEditForm(obj=user)
....
但是这次没有设置城市默认值。我更改了这样的表格:
def __init__(self, *args, **kwargs):
super(UserEditForm, self).__init__(*args, **kwargs)
self.state.choices = [(state.id, state.name)
for state in State.query.order_by('name').all()]
self.city.choices = [(city.id, city.name)
for city in City.query.filter_by(state_id=kwargs['obj'].city.state_id).order_by('name').all()]
但是没有用。我尝试了许多解决方案,最后我将城市变量名称更改为usercity:
def __init__(self, *args, **kwargs):
kwargs['city'] = kwargs['obj'].city_id
super(UserEditForm, self).__init__(*args, **kwargs)
self.state.choices = [(state.id, state.name)
for state in State.query.order_by('name').all()]
self.city.choices = [(city.id, city.name)
for city in City.query.filter_by(state_id=kwargs['obj'].city.state_id).order_by('name').all()]
和usercity= SelectField("city", coerce=int)
至kwargs['city'] = kwargs['obj'].city_id
。表示它正常工作。
问题在于,当我设置kwargs['usercity'] = kwargs['obj'].city_id
时,城市选择字段的默认值将从我在obj=user
模型中定义的kwargs['obj'].city
中读取。
答案 7 :(得分:0)
Python Flask SelectField choices
# method 1 - routes.py
form.proj_cat_id.default = table1.proj_cat_id
form.process() # for preset
# method 2 - routes.py
form.proj_cat_id.process_formdata([table1.proj_cat_id])
# method 3 - routes.py
proj_cat_id_default = table1.proj_cat_id
return render_template('abc.html',proj_cat_id_default=proj_cat_id_default)
# method 3 - abc.html
{% set z = form.proj_cat_id.process_data(proj_cat_id_default) %}
{{ form.proj_cat_id(class="form-control form-control-lg") }}