【问题标题】:flask-wtf form validation not working for my new appflask-wtf 表单验证不适用于我的新应用
【发布时间】:2013-07-17 19:35:28
【问题描述】:

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

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)

【问题讨论】:

  • 你能从实际使用表单的视图中显示代码吗?
  • 我将在编辑中添加我拥有的内容,但我经常搞砸它,因为没有任何效果。当我输入无效的 subreddit 时,而不是重新加载页面或任何内容,它只会在 pic 变量中引发错误,因为它无法从无效的 sub 获取 json

标签: python flask flask-wtforms


【解决方案1】:

你有很多问题。

最重要的是验证发生在 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')

【讨论】:

  • 感谢您的帮助,我会将其标记为我的答案,但我仍然遇到问题,我现在没有时间解决。希望很快我会修复它,但如果你想检查它,我已经更新了我的代码
  • 还是错了。不要使用request.form['subreddit'],而是使用form.subreddit.data。此外,不要检查request.method == 'POST',而是向上移动validate_on_submit 调用来代替它。您应该只在表单验证成功后更新数据库。
  • 我又更新了一次代码,但还是不行。当我将该字段留空时,将运行正确的代码,并重新加载页面并显示错误消息。但是,当我输入有效文本时,它仍然失败?我无法让 form.validate 中的代码正常工作,它只是被忽略了,因为 form.validate 没有获取正确的文本
  • 你在渲染 {{form.user}} 吗?该字段还附加了一个验证器,如果您不将其呈现给表单,则验证将永远无法工作。
  • 啊,谢谢,我现在有一个可以工作的应用程序。我将表格分为两种不同的类型,并且比每件事都有效
【解决方案2】:

Flask-WTF 在名为validate_on_submit() 的表单中添加了一个新方法。这类似于 WTForms validate() 方法,但挂钩到 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(),如上所示。

【讨论】:

  • 对不起,我不明白你的问题。也许用您所做的更改来编辑答案?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多