flask-wtf表单验证不适用于我的新应用程序

时间:2013-07-18 17:41:07

标签: python flask flask-wtforms

之前我使用过烧瓶,并且我已经进行了工作表单验证,但由于某种原因,它不能用于我的新应用程序。这是表单的基本代码。

from flask.ext.wtf import Form, TextField, TextAreaField, SubmitField, validators,ValidationError

class subReddit(Form):
    subreddit = TextField('subreddit', [validators.Required('enter valid subreddit')])
    next = SubmitField('next')
    change = SubmitField('change')
    user = TextField('user', [validators.Required('enter valid user')])
    fetch = SubmitField('fetch comments')

我有subreddit作为验证字段,所以如果它是空的,我希望它抛出错误并重新加载页面。

HTML:

<form class='sub' action="{{ url_for('sr') }}" method='post'>
  {{ form.hidden_tag() }}                    
  <p>
    if you want to enter more than one subreddit, use the + symbol, like this:
    funny+pics+cringepics
  <p>
    <br/>
    {% for error in form.subreddit.errors %}
  <p>{{error}}</p>
  {% endfor %}
  {{form.subreddit.label}}
  {{form.subreddit}}
  {{form.change}}                    
</form>

我的routes.py中也有CSRF_ENABLED = True。我错过了什么?当我将subredditfield留空并单击更改时,它只是重新加载页面,没有错误。这是一个问题,因为该字段中的任何内容都将记录在我的数据库中,并且它不能为空。

修改

@app.route('/index',methods=['GET','POST'])
@app.route('/',methods=['GET','POST'])
def index():
form = subReddit()     
rand = random.randint(0,99)
sr = g.db.execute('select sr from subreddit')       
srr = sr.fetchone()[0]
r = requests.get('http://www.reddit.com/r/{subreddit}.json?limit=100'.format(subreddit=srr))
j = json.loads(r.content)     
pic = j['data']['children'][rand]['data']['url'] 
title = None
if form.validate_on_submit():
    g.db.execute("UPDATE subreddit SET sr=(?)", [form.subreddit.data])          
    print 'validate ' 
    if j['data']['children'][rand]['data']['url']:   
        print 'pic real'                
        sr = g.db.execute('select sr from subreddit')       
        srr = sr.fetchone()[0]  
        r = requests.get('http://www.reddit.com/r/{subreddit}.json?limit=100'.format(subreddit=srr))
        pic = j['data']['children'][rand]['data']['url']
        title = str(j['data']['children'][rand]['data']['title']).decode('utf-8')   
        return render_template('index.html',form=form,srr=srr,pic=pic,title=title)
    else:
        print 'not valid pic'
        return render_template('index.html',form=form,srr=srr,pic=pic)
else:
    print 'not valid submit'
    return render_template('index.html',form=form,srr=srr,pic=pic)           
return render_template('index.html',form=form,srr=srr,pic=pic)

2 个答案:

答案 0 :(得分:8)

你有很多问题。

最重要的是验证发生在POST请求视图功能中。在您的示例中,这是函数sr。该函数应该创建表单对象并在将内容添加到数据库之前对其进行验证。

您的代码中的另一个问题(假设上述问题已修复)是​​在验证失败后您重定向。正确的做法是在不重定向的情况下将模板呈现在那里,因为验证产生的错误消息会加载到该表单实例中。如果您重定向,则会丢失验证结果。

此外,请使用validate_on_submit代替validate,因为这样您就不必检查request.method == 'POST'

示例:

@app.route('/sr', methods=['POST'])    
def sr():
    form = subReddit()
    if not form.validate_on_submit():
        return render_template('index.html',form=form)
    g.db.execute("UPDATE subreddit SET sr=(?)", [form.subreddit.data])      
    return redirect(url_for('index'))

其他建议:

  • 通常的做法是使用大写字符启动您的类名。 SubReddit优于subReddit
  • 在同一视图函数中为基于表单的页面提供GET和POST请求处理程序也很常见,因为在验证失败时保持URL清洁,而不必跳过箍以使重定向工作。您可以将其与sr结合使用,并将表单中的操作转到index()
  • ,而不是单独使用url_for('index')功能。

答案 1 :(得分:2)

Flask-WTF在名为validate_on_submit()的表单上添加了一个新方法。这就像WTForms validate()方法,但挂钩到Flask框架以访问post数据。 Flask网站上给出的例子是:

form = MyForm()
if form.validate_on_submit():
    flash("Success")
    return redirect(url_for("index"))
return render_template("index.html", form=form)

因为你只是使用了validate(),所以表单试图在没有任何数据的情况下进行验证(当然,这会失败)。然后你重定向。尝试使用validate_on_submit(),如上所示。