You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 12:20:26