Life is Really Short, Have Your Life!!

ござ先輩の主に技術的なメモ

WTFormsのSelectFieldで選択値(selected)を保持する方法

WTFormsはこの辺がイケてないのぅ。

SelectFieldで選択した値を元に検索をかけると、Ajaxでもなければ初期値の値に戻ってしまう。SelectFieldにはdefaultというプロパティがあるが、これはコンストラクタでしか有効にならない。

#これだと選択値が入る
select = SelectField(
    choices=[(1, 'First'), (2, 'Second')], 
    default=2) 

#これはダメ
select = SelectField(choices=[(1, 'First'), (2, 'Second')])
select.default = 2 #NG

初期値と選択値は全く別になるようだ。ぐぐったら全く同じことをやりたい人がいた。

Change default value of a SelectField after form creation · Issue #106 · wtforms/wtforms · GitHub

class MySelectField(SelectField):
    def iter_choices(self):
        current_value = self.data if self.data is not None else self.coerce(self.default)
        for value, label in self.choices:
            yield (value, label, self.coerce(value) == current_value)

QuerySelectFieldの場合

これも似たようなアプローチで実現している人がいた。

Extended QuerySelectField to allow SQLAlchemy objects to be passed in as default avalues

ただ、上記のままでは動かない。こうすれば動く。

class MyQuerySelectField(QuerySelectField):
    selected = None

    def iter_choices(self):
        if self.allow_blank:
            yield ('', self.blank_text, self.data is None)

        for pk, obj in self._get_object_list():
            if self.selected is not None and self.selected == obj.id:
                yield (pk, self.get_label(obj), True)
            else:
                yield (pk, self.get_label(obj), obj == self.data)