Flask WTForms如何防止表单重复提交?
防止Flask表单重复提交的几种实用方法
1. 前端点击后禁用提交按钮
最直接的前端拦截方式,用户点击提交按钮后立刻禁用,避免重复触发提交动作。修改你的模板代码:
<div class="form-group"> {{ add_note_form.add_note(onclick="this.disabled=true; this.form.submit();") }} </div>
如果想优化用户体验,可以添加加载提示:
<div class="form-group"> {{ add_note_form.add_note(id="add-note-btn") }} </div> <script> const submitBtn = document.getElementById('add-note-btn'); submitBtn.addEventListener('click', function(e) { if (!this.disabled) { this.disabled = true; this.textContent = '提交中...'; this.form.submit(); } else { e.preventDefault(); } }); </script>
2. 采用Post/Redirect/Get (PRG)模式
这是Web开发的标准最佳实践,处理完POST请求后重定向到GET路由,从根源上避免刷新页面重复提交的问题。
修改你的router.py代码:
from flask import redirect, url_for, render_template, flash @app.route('/add-note', methods=['GET', 'POST']) def add_note(): add_note_form = forms.NoteForm() if add_note_form.validate_on_submit(): # 执行保存笔记的逻辑(例如写入数据库) save_note(add_note_form.note.data) flash('笔记添加成功!') # 重定向到笔记列表页或当前页面的GET路由 return redirect(url_for('note_list')) # note_list为你定义的展示笔记的路由 return render_template('note_form.html', add_note_form=add_note_form)
提交完成后用户会跳转到新页面,即使刷新或后退再提交,也只会重新加载空表单,不会重复执行保存逻辑。
3. 利用Flask-WTF的CSRF令牌实现一次性提交
Flask-WTF默认自带CSRF保护,我们可以让提交后的CSRF令牌失效,阻止重复提交。
修改路由代码:
from flask import flash @app.route('/add-note', methods=['GET', 'POST']) def add_note(): add_note_form = forms.NoteForm() if add_note_form.validate_on_submit(): # 执行保存笔记逻辑 save_note(add_note_form.note.data) flash('笔记添加成功!') # 重新生成表单,旧CSRF令牌失效 add_note_form = forms.NoteForm() return render_template('note_form.html', add_note_form=add_note_form)
用户如果重复提交(比如后退再提交),旧的CSRF令牌已无效,表单会验证失败。
4. 后端记录请求唯一标识
通过生成唯一令牌并验证使用状态,在后端层面拦截重复提交。
首先修改Forms.py添加隐藏字段:
class NoteForm(FlaskForm): note = fields.TextAreaField("Note") submit_token = fields.HiddenField() add_note = fields.SubmitField("Add Note")
然后在路由中处理令牌验证:
import uuid from flask import session, flash, redirect, url_for @app.route('/add-note', methods=['GET', 'POST']) def add_note(): add_note_form = forms.NoteForm() # GET请求时生成唯一令牌并存入session if request.method == 'GET': submit_token = str(uuid.uuid4()) session['submit_token'] = submit_token add_note_form.submit_token.data = submit_token if add_note_form.validate_on_submit(): # 验证令牌是否有效且未被使用 if add_note_form.submit_token.data != session.pop('submit_token', None): flash('请勿重复提交表单!') return redirect(url_for('add_note')) # 执行保存笔记逻辑 save_note(add_note_form.note.data) flash('笔记添加成功!') return redirect(url_for('note_list')) return render_template('note_form.html', add_note_form=add_note_form)
这种方式即使前端禁用按钮失效,后端也能拦截重复请求。
内容的提问来源于stack exchange,提问作者William
相关产品推荐
相关产品推荐

