Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask + WTForms + SelectMultipleField and Dynamic Choices

I am trying to use WTForms.SelectMultipleField to manage some dynamic choices on a form but I'm running into some difficulty with it being modified client-side before being submitted for validation.

Basically I have two SelectMultipleField options:

class MyForm(Form):
    assigned = SelectMultipleField('Assigned', choices=[])
    available = SelectMultipleField('Available', choices=[('1','1'),('2','2')])

I'm using Flask to render Jinja2 templates like so:

@app.view("/myview", methods=['GET','POST'])
def myview():
    form = MyForm(request.form)
    if request.method == 'POST' and form.validate():
        return render_template("success.html")
    else:
        return render_template("index.html", form=form)

In my template I have this:

<script type="text/javascript">
    function assign_object() {
        return !$('#available option:selected').remove().appendTo('#assigned');
    };

    function unassign_object() {
        return !$('#assigned option:selected').remove().appendTo('#available');
    }

    $(document).ready( function() {
        $('#available').dblclick( assign_object );
        $('#assigned').dblclick( unassign_object );
    });
</script>

<form action="/myview" method="post" name="assign_objects">
    {{ render_field(form.a) }}
    {{ render_field(form.b) }}
    <input type="submit" value="Assign" name="assign_button"/>
</form>

Basically all of this works as intended; double-clicking on an item in the unassigned list moves it over to the assigned list. The issue is when the form is submitted for validation, because the .choices attribute on the "assigned" field was originally "[ ]" and is still expected to be "[ ]" rather than the new options list that we've given it.

Does anyone know a good way to do this? I was thinking I could override the forms pre_validate() function and update assigned.choices to include all the values from the "available" list, but this doesn't feel "right" and could be used to submit random values from the client-side on submit.

Cheers, David.

like image 439
2 revs Avatar asked Oct 22 '12 14:10

2 revs


1 Answers

Update choices in the POST request:

AVAILABLE_CHOICES = [('1','1'),('2','2')]
DEFAULT_CHOICES = []

class MyForm(Form):
    assigned = SelectMultipleField('Assigned', choices=DEFAULT_CHOICES)
    available = SelectMultipleField('Available', choices=AVAILABLE_CHOICES)

@app.view("/myview", methods=['GET','POST'])
def myview():
    form = MyForm(request.form)
    if request.method == 'POST':
        form.assigned.choices = AVAILABLE_CHOICES
        if form.validate():
            return render_template("success.html")
        else:
            form.assigned.choices = DEFAULT_CHOICES

    return render_template("index.html", form=form)
like image 197
Sean Vieira Avatar answered Oct 02 '22 08:10

Sean Vieira