SelectFieldのデフォルト値をWTFormsで設定しようとすると、そのように '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のデフォルト値をどのように設定しますか?」
あなたが投稿した最初の方法は正しいです、そしてそれは私のために働きます。それが機能しない唯一の説明は、あなたがWTFormsの古いバージョンを実行しているということです、それは1.0.1で私のために働いた
この問題はField
のdata
属性がWTFormsが理解できないもの(たとえば、DBモデルオブジェクト-default
を期待するもの)でint
をオーバーライドすることによって引き起こされると考えています。 )。これは、コンストラクタでフォームに次のように入力した場合に発生します。
form = PostForm(obj=post)
解決策は、フォームにデータを入力した後、data
属性を手動で設定することです。
form = PostForm(obj=post)
form.category.data = (post.category.id
if page.category
else 0) # I make 0 my default
これを行うにはいくつかの方法があります。最初のコードスニペットは確かに正しいです。
ただし、ビューでこれを動的に行う場合は、次のこともできます。
form = TestForm()
form.test_field.default = some_default_id
form.process()
_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():
...
_
これは、choices
を使用するときにSelectField
を使用したint
設定です。次のように機能します。
test_select = SelectField("Test", coerce=int, choices=[(0, "test0"), (1, "test1")], default=1)
または:
class TestForm(Form):
test_select = SelectField("Test", coerce=int)
@app.route("/test")
def view_function():
form = TestForm()
form.test_select.choices = [(0, "test0"), (1, "test1")]
form.test_select.default = 1
form.process()
便利だと思う動的設定のデフォルト選択フィールドに問題があります。モデルは次のようなものでした:
class State(db.Model):
__table= 'states'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(128), nullable=False)
class City(db.Model):
__table= '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()]
そして、ビューは次のようでした:
@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)
....
正常に機能し、Selectfieldのデフォルト値を正しく設定します。しかし、私はこのようにコードを変更しました:
ビュー:
@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()]
しかし、今回は都市のデフォルト値は設定されていません。このようにフォームを変更しました:
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に変更しました:
usercity= SelectField("city", coerce=int)
およびkwargs['city'] = kwargs['obj'].city_id
からkwargs['usercity'] = kwargs['obj'].city_id
へ。それが正常に動作したことの後に。
問題は、obj=user
を設定したときに、user
モデルで定義したkwargs['obj'].city
から都市選択フィールドのデフォルト値が読み取られることでした。
Flask_wtfを使用していて、このようなFieldListにネストされた異なるSelectFieldsにデフォルト値を設定したい場合
_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 副作用があります:data
を上書きしている場合、form.validate_on_submit()
は機能しません! validate_on_submit()
を呼び出すときにdata
の上書きを無効にする簡単な回避策を構築できます。
_ 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:私の評判は低すぎて、エリオットの正しい答えに直接コメントすることはできません。