web-dev-qa-db-ja.com

WTForms SelectFieldのデフォルト値をどのように設定しますか?

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のデフォルト値をどのように設定しますか?」

38
jan

あなたが投稿した最初の方法は正しいです、そしてそれは私のために働きます。それが機能しない唯一の説明は、あなたがWTFormsの古いバージョンを実行しているということです、それは1.0.1で私のために働いた

27
sp.

この問題はFielddata属性が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
34
Elliott C

これを行うにはいくつかの方法があります。最初のコードスニペットは確かに正しいです。

ただし、ビューでこれを動的に行う場合は、次のこともできます。

form = TestForm()
form.test_field.default = some_default_id
form.process()
14
getup8

_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():
    ...
_
12
greedy52

これは、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()
6
Liu Yue

便利だと思う動的設定のデフォルト選択フィールドに問題があります。モデルは次のようなものでした:

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から都市選択フィールドのデフォルト値が読み取られることでした。

0
Tavakoli

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:私の評判は低すぎて、エリオットの正しい答えに直接コメントすることはできません。

0
konstantin