LoginSignup
3
2

More than 5 years have passed since last update.

WTFormsでSelectのOptionに任意のattributeを付ける

Last updated at Posted at 2019-05-31

やりたかったこと、解決方針

WTFormsでselectplaceholderを付けたかった。
Bootstrapを入れているので単にoptionclass="hidden"を入れれば良いが、htmlはwtf.quickFormを使いたかったので、Formクラスでなんとかならないかを調べた。
調べた結果Fieldクラスを作らないとダメそうだったので、どうせならclass属性だけじゃなくなんでも入れられるようにしたくなった。

環境

  • python 3.6.7
  • WTForms 2.2.1
  • flask-Bootstrap 3.3.7.1

ソース

WTForms.SelectFieldWTForms.widgets.Selectを拡張した

field.py
from flask_wtf import FlaskForm
from wtforms import SelectField
from wtforms.widgets import Select, HTMLString, html_params

# WTForms.widgets.Selectを拡張
class SelectHasAttributesOption(Select):
    def __call__(self, field, **kwargs):
        kwargs.setdefault('id', field.id)
        if self.multiple:
            kwargs['multiple'] = True
        if 'required' not in kwargs and 'required' in getattr(field, 'flags', []):
            kwargs['required'] = True
        html = ['<select %s>' % html_params(name=field.name, **kwargs)]
        for val, label, selected, render_kw in field.iter_choices_with_render_kw(): # 追加:render_kw 変更:iter_choices_with_render_kw
            html.append(self.render_option(val, label, selected, **render_kw)) # 追加:**render_kw
        html.append('</select>')
        return HTMLString(''.join(html))

# WTForms.SelectFieldを拡張
class SelectHasAttributesOptionField(SelectField):
    widget = SelectHasAttributesOption()

    def iter_choices(self):
        for value, label, *_ in self.choices:
            yield (value, label, self.coerce(value) == self.data)

    def pre_validate(self, form):
        for v, *_ in self.choices:
            if self.data == v:
                break
        else:
            raise ValueError(self.gettext('Not a valid choice'))

    def iter_choices_with_render_kw(self):
        for value, label, *render_kw in self.choices:
            render_kw = render_kw[0] if render_kw else {}
            yield (value, label, self.coerce(value) == self.data, render_kw)

使い方

SelectFieldの代わりにSelectHasAttributesOptionFieldを使い、choicesのタプルにrender_kw的に辞書を追加する。

ソース

from flask_wtf import FlaskForm
from .field import SelectHasAttributesOptionField

class TestForm(FlaskForm):
    select = SelectHasAttributesOptionField(
        'ラベル', 
        choices=[
            ('', '選択して', {'class': 'hidden'}), 
            ('1', '1'), 
            ('2', '2')
        ]
    )

実行

初期表示
image.png
選択肢にplaceholderは表示されない
image.png

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2