web-dev-qa-db-fra.com

Flask-WTF - validate_on_submit () n'est jamais exécuté

J'utilise Flask-WTF:

Voici mon formulaire:

from flask.ext.wtf import Form, TextField

class BookNewForm(Form):
    name = TextField('Name')

Voici le contrôleur:

@book.route('/book/new', methods=['GET', 'POST'])
def customers_new():
    form = BookNewForm()
    if form.is_submitted():
        print "submitted"
    if form.validate():
        print "valid"
    if form.validate_on_submit():
        flash("Successfully created a new book")
        return redirect(url_for('.books_show'))
    return render_template('views/books_new.html', form=form)

Maintenant, le problème est que, si vous regardez mes instructions print, il imprime toujours soumis, mais il ne imprime JAMAIS valide et validate_on_submit () n'est jamais exécuté. Pourquoi?

26
kadrian

Vous n'insérez pas le champ CSRF dans le formulaire HTML.

<form method=post>
    {{ form.csrf_token }}
    {{ form.name }}
    <input type=submit>
</form>

Après avoir ajouté form.csrf_token au modèle ( docs ), le formulaire sera validé comme prévu.

Ajoutez print(form.errors) après avoir validé le formulaire pour afficher les erreurs générées. errors sera vide avant validation. Dans ce cas, il y a une erreur à propos de manquer

@book.route('/book/new_no_csrf', methods=['GET', 'POST'])
def customers_new_no_csrf():
    form = BookNewForm()
    print(form.errors)

    if form.is_submitted():
        print "submitted"

    if form.validate():
        print "valid"

    print(form.errors)

    if form.validate_on_submit():
        flash("Successfully created a new book")
        return redirect(url_for('.books_show'))

    return render_template('books_new.html', form=form)
{}
submitted
{'csrf_token': [u'CSRF token missing']}
127.0.0.1 - - [29/May/2012 02:01:08] "POST /book/new_no_csrf HTTP/1.1" 200 -
127.0.0.1 - - [29/May/2012 02:01:08] "GET /favicon.ico HTTP/1.1" 404 -

J'ai créé un exemple sur GitHub.

41
A.Ford

vous pouvez imprimer des erreurs

print form.errors

ou 

app.logger.debug(form.errors)

et si vous obtenez une erreur csrf, vous devez définir form.csrf_token dans votre modèle. 

11
kzfm

insérez ceci après la balise dans le fichier HTML du modèle:

 {{ form.csrf_token }} 
2
lihuanshuai

Je suis tombé sur cette erreur en essayant de restituer une FormField itérée sur ma FieldList dans mon modèle. Je devais intégrer deux éléments cachés, l'un pour le formulaire FieldList et l'autre pour le formulaire FieldForm, recherchez dans les commentaires du modèle le mot clé "HIDDEN TAG".

class ParamRangeForm( FlaskForm ):
    minX = FloatField( )
    maxX = FloatField( )

class ParamRangesForm( FlaskForm ):
    paramRanges = FieldList( FormField( ParamRangeForm ) )
    submit      = SubmitField( 'Submit' )

    def loadParams( self ) :
        for paramName in ["p1" , "p2" , "p3", "p4"] :
            prf = ParamRangeForm( )
            prf.minX = -100.9#float('-inf')
            prf.maxX = 100.5#float('-inf')
            self.paramRanges.append_entry( prf )

...

  <form action="" method="POST" enctype="multipart/form-data">
    {{ rangesForm.hidden_tag() }} <!--#### HIDDEN TAG #1 -->
    <table>
      <!--Print Column Headers-->
      <thead>
      <tr>
        <th class="ColumnHeader">Parameter</td>
        <th class="ColumnHeader">Min</td>
        <th class="ColumnHeader">Max</td>
      </tr>
      </thead>

      <!--Print Parameter Rows-->
      <tbody>
      {% for paramRange in rangesForm.paramRanges %}
        <tr>
          {{ paramRange.hidden_tag() }} <!--#### HIDDEN TAG #2 -->
          <td>p{{ loop.index }}</td>
          <td>{{ paramRange.minX }}</td>
          <td>{{ paramRange.maxX }}</td>
        </tr>
      {% endfor %}
      </tbody>
    </table>
    </div>
    {{ rangesForm.submit() }}
  </form>
1
jxramos

J'étais en train de vider la session du flacon si je n'étais pas connecté avant chaque demande. Cela causait ce problème.

@main.before_request
def before_request():
    if not current_user.is_authenticated():
        # TODO clean sessions may cause CSRF missing issue
        session.clear()
        print "Session Cleared"
        return redirect(url_for('auth.login'))
1
tourdownunder

Je pense que l'API a changé.Peut-être essayer de changer 

from flask.ext.wtf import Form

à:

from flask_wtf import Form
0
Kanav Anand