2

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

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)
4

2 回答 2

10

你有很多问题。

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

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

此外,使用validate_on_submit代替validateas 可以使您不必检查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()go to 形式的操作结合起来url_for('index')
于 2013-07-18T18:40:39.437 回答
2

Flask-WTF 在名为validate_on_submit(). 这类似于 WTFormsvalidate()方法,但挂钩到 Flask 框架以访问发布数据。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()如上图。

于 2013-07-18T18:04:47.130 回答