RoB
RoB

Reputation: 1984

Passing a variable defined in previous form to another form

So I have this flask app I'm making and I need some help with a variable access.

Most of the time, when you define a form in flask, you'll do the following :

class MyForm(Form):
    my_field = StringField('I'm a field')
    my_submit = SubmitField('Go!')

And when the time comes where you need the form, you'll declare an instance of that class with form = MyForm()

Up to here, it's all good, However :

If you want say, a SelectField (Dropdown) where the choices depend on the answers of a previous form, you need to be able to give the new form those choices. This is what I'm trying to achieve, but I can't get a variable to keep its contents.

Here is my Form code (Above the page code):

class DataMappingForm(Form):

    dm_choices = #I need this array !

    DMpatient_id = SelectField(u'Select Patient ID Column', 
            choices=dm_choices, validators=[Required()])
    ...

Here is my Page code :

@app.route('/upload', methods=['GET','POST'])
def upload():
    uform = SomeOtherForm()
    if uform.is_submitted() and uform.data['Usubmit']:
        #Do stuff from previous form
        # and declare array_of_choices
    dmform = DataMappingForm() #Needs array_of_choices to work
    ...

What I've tried so far :

I should mention, this all needs to be on the same page.

Is there a way to pass this array_of_choices to my DataMappingForm class ?

EDIT This is what it looked like when I trid the __init__ overload:

class DataMappingForm(Form):
     def __init__(self, dm_choices, *args, **kwargs):
         self.dm_choices = dm_choices
         Form.__init__(self, *args, **kwargs)

     DMpatient_id = SelectField(u'Select Patient ID Column', 
             choices=dm_choices, validators=[Required()])
#I've tried putting it above or below, I get 'dm_choices is not defined'

Upvotes: 1

Views: 1172

Answers (2)

syntonym
syntonym

Reputation: 7384

If you want to dynamically change the choices of a SelectField the following should work:

class DataMappingForm(Form):

    def __init__(self, choices)
        self.DMpatient_id.choices = choices

    DMpatient_id = SelectField(u'Select Patient ID Column') #note that choices is absent

If you want fully dynamic fields you can create the class dynamically in a function. From the WTForms Documentation:

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

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

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

In that case you can customize the form as much as you want. Of course in the case you only want to customize the choices the first approach should be enough.

Upvotes: 0

RoB
RoB

Reputation: 1984

I've Got it ! Thanks to @synonym for pointing me in the right direction with your last link.

All you need to do is declare a function in which the class is defined. You then pass the variable to the function, and it will be accessible within the class.

Finally, make the function return the form object.

Example :

def makeMyForm(myArray):
    def class MyForm(Form):
        my_select_field = SelectField(u'I'm a select field', choices=myArray)
        my_submit = SubmitField(u'Go!')
    return MyForm()

And to make the form, you use :

form = makeMyForm(theArrayYouWant)

And Voilà !

Note : As I've had the problem before, I'll mention that the Array is composed of tuples :

myArray = [('value','What you see'),('value2','What you see again')]

Upvotes: 1

Related Questions