Search code examples
pythonflaskcsrf

Flask-WTF SelectField with CSRF protection enabled


I'm having a problem when submitting a form containing a dynamically populated SelectField. For some reason when Flask tries to validate the CSRF token it always fails when the SelectField is in the form. When I remove the SelectField from the form, it validates the CSRF token successfully.

Has anyone come across this behavior?

EDIT

Form:

class AddToReportForm(Form):
    selectReportField = SelectField(u'Reports',choices=[('test1','test')])

    def __init__(self, *args, **kwargs):
        """
        Initiates a new user form object
        :param args: Python default
        :param kwargs: Python default
        """
        Form.__init__(self, *args, **kwargs)




    def validate(self,id_list):
        rv = Form.validate(self)

        if not rv:
            print False
            #Check for the CSRF Token, if it's not there abort.
            return False

        print True
        return True

Jinja2:

<form  method=post name="test">
{{ form.hidden_tag()}}




    {{ form.selectReportField }}
    <a href="#" onclick="$(this).closest('form').submit()" class="button save">Add to report</a>

</form>

Rendering:

form = AddToReportForm()
return render_template('random',title='add reports',form=form

Solution

  • I still can't see any connection between SelectField and CSRF. The validate method is little suspicious and the extra argument would trip the following testcase, but as it stands this seems to work just fine:

    from flask import Flask, render_template_string
    from flaskext.wtf import Form, SelectField
    
    app = Flask(__name__)
    app.debug = True
    app.secret_key = 's3cr3t'
    
    
    class AddToReportForm(Form):
        selectReportField = SelectField(u'Reports', choices=[('test1', 'test')])
    
    
    @app.route('/test', methods=['GET', 'POST'])
    def test():
        form = AddToReportForm()
        if form.validate_on_submit():
            print 'OK'
        return render_template_string('''\
    <form method=post name="test">
    {{ form.hidden_tag()}}
    {{ form.selectReportField }}
    <input type="submit">
    </form>
    ''', form=form)
    
    
    app.run(host='0.0.0.0')