Проверка формы flask-wtf не работает для моего нового приложения

Я использовал флягу раньше, и у меня была рабочая проверка формы, но по какой-то причине она не работает для моего нового приложения. Вот основной код формы.

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>

У меня также есть CSRF_ENABLED=True в моем файле route.py. Что мне не хватает? Когда я оставляю поле 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)

person gallly    schedule 18.07.2013    source источник
comment
Можете ли вы показать код из представления, которое фактически использует форму?   -  person Mark Hildreth    schedule 18.07.2013
comment
Я добавлю то, что у меня есть в редактировании, но я много возился с этим, потому что ничего не работает. Когда я ввожу недопустимый сабреддит, вместо того, чтобы перезагружать страницу или что-то еще, он просто выдает ошибку в переменной pic, потому что не может получить json из недопустимого сабвуфера.   -  person gallly    schedule 18.07.2013


Ответы (2)


У вас есть ряд проблем.

Наиболее важным является то, что проверка происходит в функции просмотра запроса 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').
person Miguel    schedule 18.07.2013
comment
спасибо за эту помощь, я отмечу это как свой ответ, но у меня все еще есть проблемы, на решение которых у меня сейчас нет времени. Надеюсь, скоро я это исправлю, но я обновил свой код, если вы хотите его проверить. - person gallly; 19.07.2013
comment
Это все еще неправильно. Не используйте request.form['subreddit'], вместо этого используйте form.subreddit.data. Кроме того, вместо проверки request.method == 'POST' переместите вверх вызов validate_on_submit, чтобы занять его место. Вы должны обновлять базу данных только после успешной проверки формы. - person Miguel; 19.07.2013
comment
Я обновил код еще раз, но он не работает. Когда я оставляю поле пустым, запускается правильный код, и он перезагружает страницу с сообщением об ошибке. Но когда я ввожу правильный текст, он все равно терпит неудачу? Я не могу заставить свой код в form.validate работать, он просто игнорируется, потому что form.validate не получает правильный текст - person gallly; 19.07.2013
comment
Вы рендерите {{form.user}}? К этому полю также прикреплен валидатор, если вы не отобразите его в форме, проверка никогда не будет работать. - person Miguel; 19.07.2013
comment
ах, спасибо, теперь у меня есть рабочее приложение. Я разделил форму на 2 разных вида, и все заработало. - person gallly; 22.07.2013

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(), как показано выше.

person Mark Hildreth    schedule 18.07.2013
comment
Извините, я не понимаю вашего вопроса. Возможно, отредактируйте ответ с внесенными вами изменениями? - person Mark Hildreth; 18.07.2013