13

質問は異なるが回答は同じであるいくつかのフォーム フィールドを動的に作成するにはどうすればよいでしょうか。

from wtforms import Form, RadioField
from wtforms.validators import Required

class VariableForm(Form):

    def __init__(formdata=None, obj=None, prefix='', **kwargs):
        super(VariableForm, self).__init__(formdata, obj, prefix, **kwargs)
        questions = kwargs['questions']
        // How to to dynamically create three questions formatted as below?

    question = RadioField(
            # question ?,
            [Required()],
            choices = [('yes', 'Yes'), ('no', 'No')],
            )

questions = ("Do you like peas?", "Do you like tea?", "Are you nice?")  
form = VariableForm(questions = questions)
4

3 に答える 3

17

それはずっとドキュメントにありました。

def my_view():
    class F(MyBaseForm):
        pass

    F.username = TextField('username')
    for name in iterate_some_model_dynamically():
        setattr(F, name, TextField(name.title()))

    form = F(request.POST, ...)
    # do view stuff

私が気付いていなかったのは、インスタンス化が発生する前にクラス属性を設定する必要があるということです。明快さは、このビットバケットのコメントから来ています:

これはバグではなく、仕様によるものです。インスタンス化されたフォームにフィールドを追加する際には、多くの問題があります。たとえば、データは Form コンストラクターを介して取得されます。

リンクしたスレッドを読み直すと、クラスを派生させ、それにフィールドを追加し、新しいクラスをインスタンス化する必要があることに気付くでしょう。通常、これはビュー ハンドラー内で行います。

于 2012-07-26T04:42:02.343 に答える
1

あなたはほとんどそこにいます:

CHOICES = [('yes', 'Yes'), ('no', 'No')]

class VariableForm(Form):

    def __new__(cls, questions, **kwargs):
        for index, question in enumerate(questions):
            field_name = "question_{}".format(index)
            field = RadioField(question,
                                  validators=[Required()],
                                  choices=CHOICES)
            setattr(cls, field_name, field)
        return super(VariableForm, cls).__new__(cls, **kwargs)
于 2012-07-24T03:37:27.537 に答える