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")
        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 );

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

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.

10/22/2012 2:21:23 PM

Accepted Answer

Update choices in the POST request:

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

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")
            form.assigned.choices = DEFAULT_CHOICES

    return render_template("index.html", form=form)
10/22/2012 10:01:03 PM

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow