如何解决Flask+DynamoDB应用中浏览器刷新导致表单重复提交的问题
解决Flask表单提交后刷新重复插入DynamoDB的问题
这个问题太常见了——当你通过POST请求提交表单后,浏览器会把这次POST请求的内容保存下来,点击刷新按钮时,浏览器就会重新发送一遍相同的POST请求,自然就导致DynamoDB里被重复插入数据了。最标准且彻底的解决方案是使用PRG模式(Post/Redirect/Get),下面结合你的代码给出具体修改方案:
方法一:实现PRG模式(推荐)
核心逻辑:处理完POST请求后,不直接返回渲染好的模板,而是重定向到一个GET请求路由(可以是同一个路由的GET分支),同时用Flask的flash机制传递操作提示信息。这样刷新时只会发送GET请求,不会触发重复提交。
修改后的Flask后端代码
from flask import Flask, request, render_template, redirect, url_for, flash # 初始化app时必须设置secret_key,flash功能依赖它 app = Flask(__name__) app.secret_key = 'your_random_secret_key_here' # 替换成任意随机字符串即可 @app.route('/',methods = ['GET','POST']) def parseurl(): if request.method == 'GET': return render_template('index.html') else: mesg = '' if "url" in request.form and "name" in request.form: URL = request.form.get("url") if validators.url(URL): org_name = request.form.get("name") trans = { 'url': URL, 'organization_name': org_name } try: table.put_item(Item=trans) mesg = 'Data Saved Successfully' except Exception as e: # 打印异常方便调试(生产环境可去掉或改为日志记录) print(f"Insert error: {str(e)}") mesg = 'Data Insertion Not Successful' else: mesg = 'Not a valid URL' else: mesg = 'Incomplete Form Data Submitted' # 用flash存储提示信息,然后重定向到GET请求的同一路由 flash(mesg) return redirect(url_for('parseurl'))
修改后的HTML前端代码
需要替换原来的结果展示区域,改为渲染flash消息:
<body> <!-- Navbar--> <nav class="navbar navbar-dark bg-dark"> <span class="navbar-brand mb-0 h1">SCRAPE DATA</span> </nav> <br> <h3 style="margin: auto;width: 80%; text-align: center; margin-top: 20px; text-transform: uppercase">SCRAPE DATA</h3> <div class="container"> <!-- 新增:显示flash提示消息 --> {% with messages = get_flashed_messages() %} {% if messages %} {% for message in messages %} <div id="result"> <strong style="color:red">{{ message }}</strong> </div> {% endfor %} {% endif %} {% endwith %} <form action = "{{url_for('parseurl')}}" method ="POST" > <div class="form-group"> <label for="name">Enter Organization Name</label> <input type="text" class="form-control" id="name" name="name" required> <label for="url">Enter URL to scrape</label> <input type="text" class="form-control" id="url" name="url" required> </div> <br> <div class="form-group"> <input class="btn btn-primary" type="submit" value="Scrape"> </div> </form> </div> </body>
方法二:前端辅助禁用提交按钮(可选,配合PRG使用更佳)
为了避免用户快速多次点击提交按钮导致的重复提交,可以在前端添加简单的JS代码,点击提交后立即禁用按钮:
<!-- 修改form标签,添加onsubmit事件 --> <form action = "{{url_for('parseurl')}}" method ="POST" onsubmit="disableSubmit()"> <!-- 其他表单内容不变 --> <div class="form-group"> <input class="btn btn-primary" type="submit" value="Scrape" id="submitBtn"> </div> </form> <script> function disableSubmit() { const submitBtn = document.getElementById('submitBtn'); submitBtn.disabled = true; submitBtn.value = 'Submitting...'; } </script>
为什么PRG能解决问题?
当处理完POST请求后返回重定向响应,浏览器会自动发送一个GET请求到目标路由。此时浏览器的历史记录中只会保留GET请求,刷新时只会重新发送GET请求,不会触发POST提交,从根源上避免了重复插入数据的问题。
内容的提问来源于stack exchange,提问作者Aniiya0978
相关产品推荐
相关产品推荐

