Skip to main content
 首页 » 编程设计

python之flask-wtf 表单验证不适用于我的新应用

2025年05月04日14artech

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

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。我错过了什么?当我将 subreddit 字段留空并单击更改时,它只是重新加载页面,没有错误。这是一个问题,因为该字段中的任何内容都会记录在我的数据库中,并且不能为空。

编辑

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

请您参考如下方法:

你有很多问题。

最重要的是验证发生在 POST 请求 View 函数中。在您的示例中,这是函数 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。
  • 在同一个 View 函数中使用基于表单的页面的 GET 和 POST 请求处理程序也很常见,因为这样可以在验证失败时保持 URL 的清洁,而不必通过循环来使重定向工作。不用单独使用 sr 函数,您只需将它与 index() 组合起来,然后让表单中的操作转到 url_for('index').