Phillip Cunningham
Phillip Cunningham

Reputation: 141

Add dynamic number of SelectMultipleField's to wtf-flask form

I've looked at the documentation and a couple other Q/As on here but I can't seem to make the code work. I have a basic form in a forms.py file:

class SimpleForm(Form):
    list_of_files = ['Option 1','Option 2','Option 3','Option 4','Option 5','Option 6']
    files = [(x, x) for x in list_of_files]
    acheckbox = MultiCheckboxField('Label',choices=files)
    third_list = ['Special Analysis']
    third_files = [(x, x) for x in third_list] 
    bcheckbox = MultiCheckboxField('Label', choices=third_files)
    category_1 = SelectField(u'', choices=())
    category_2 = SelectField(u'', choices=())
    category_3 = SelectField(u'', choices=())

(I populate the categories later). I also call this form in my views.py file.

form = SimpleForm()

I want to dynamically add several SelectMultipleField's (depending on the # of columns in an user uploaded csv file). I want to pass a list variable (category) with the names of the columns n=1-5 and generate that many fields with another list (unique_values) which are the values of that field. I was looking at the doc and tried to come up with this:

class F(Form):
    pass

    F.category = SelectMultipleField('category')
    for name in extra:
        setattr(F, name, SelectMultipleFields(name.title()))
    form = F(request.POST, ...)

I know it's not right. How do I modify to append SelectMultipleField's to my original "SimpleForm?" I ultimately want to generate n numbers of the following:

unique_values = [('1', 'Choice1'), ('2', 'Choice2'), ('3', 'Choice3')]
category_4 = SelectMultipleField(u"",choices=unique_values)

UPDATE: To call the form on views.py, I use the following:

select_dict = {'Geography': ['US', 'Asia', 'Europe'], 'Product Type': ['X', 'Y', 'Z']}
form= F(request.form,select_dict)

My subclass (on forms.py) is:

class F(SimpleForm):
pass
#select_dict could be a dictionary that looks like this: {category_+str(col_number): set of choices}
def __init__(self, select_dict, *args, **kwargs):
    super(SimpleForm, self).__init__(*args, **kwargs)
    print(select_dict)
    for name,choices in select_dict.items():
        test = [(x, x) for x in choices]
        setattr(F, name, SelectMultipleField(name.title(),choices=test))

I'm getting the following error: "formdata should be a multidict-type wrapper that supports the 'getlist' method"

Upvotes: 1

Views: 681

Answers (1)

lesingerouge
lesingerouge

Reputation: 1168

Basically what you are trying to do is append to SimpleForm a variable number of SelectMultipleField elements, each with a different choice set.

First of all, to add the SelectMultipleField elements to the original SimpleForm you should just subclass it (instead of the original Form) when you define F.

Second of all, you can use most of the code you already wrote, like so:

class F(SimpleForm):
    pass

#select_dict could be a dictionary that looks like this: {category_+str(col_number): set of choices}
for name,choices in select_dict.items():
    setattr(F, name, SelectMultipleFields(name.title(),choices=choices))

form = F(request.POST, ...)

To render the dynamic form in the template, you will need a custom Jinja filter (check out this answer) and maybe a simpler way to render a field (like described on this page).

Upvotes: 1

Related Questions