Flask中使用JavaScript Fetch请求实现Flash消息正常显示的问题
我用Flask开发了一个咖啡馆应用,看了两三个教程之后就开始动手尽可能实现功能。一开始我用的是这样的表单代码:
<!-- login.html --> <body> <h1>Login</h1> <div> {% for m in get_flashed_messages() %} <div>{{ m }}</div> {% endfor %} </div> <form method="POST"> <label for="email">Email</label> <input type="text" name="email" id="email"> <label for="password">Password</label> <input type="password" name="password" id="password"> <input type="submit" id="submit" value="Login"> </form> </body>
控制器代码是这样的:
from flask import * app = Flask(__name__) app.secret_key = 'secret' app.debug = True @app.route("/", methods=['GET', 'POST']) def login(): if request.method == 'POST': email = request.form.get('email') pwd = request.form.get('password') if email and pwd: flash("Success!") return redirect(url_for('home')) else: flash("Email and password required!") return render_template('login.html') @app.route("/home/") def home(): return render_template('home.html') if __name__ == '__main__': app.run()
当表单填写不完整时,点击提交按钮页面会“重载”,并在同一页面显示Flash消息,这符合预期;当表单填写完整时,会在home.html页面显示Flash消息,这也没问题。home.html的代码是:
<!-- home.html --> <!DOCTYPE html> <html> <body> <div> {% for m in get_flashed_messages() %} <div>{{ m }}</div> {% endfor %} </div> <h1>Logging successful</h1> </body> </html>
但问题来了,当我尝试用JavaScript的Fetch API发送JSON请求来实现“同样的功能”时,就出问题了。我的JS代码是这样的:
<script> window.onload = function () { let email = document.getElementById('email'); let pwd = document.getElementById('password'); let submit = document.getElementById('submit'); submit.addEventListener('click', async function () { let data = {'email': email.value, 'password': pwd.value }; let request = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }; let response = await fetch("/", request) console.log(response); }); } </script>
这种方式下页面不会“重载”,而且Flash消息也没有像预期那样显示出来。**我想要的是用JavaScript提交数据,然后让Flash消息像原来用表单提交那样正常显示——就像用表单提交一样,但不用表单。**这到底能不能实现啊?我已经卡了一个月了,快放弃了。
对了,为了用JS发送请求,我把<form>改成了<div>,而且在控制器里改成了读取request.json。
我看过Flask的官方文档,但里面只展示了用HTML表单提交的例子,也就是我最开始写的那种。
我还试过把响应转成文本:let response = await fetch("/", data).then(r => r.text()),日志里显示返回的HTML确实包含了Flash消息,就在里面,但页面就是没反应,也不显示消息。我还看到有人说可以手动重定向,比如if(response.redirected) window.location.href = response.url,这样确实会重定向,但还是不显示Flash消息。
我不想用这种方式重写HTML:
document.open(); document.write(html); document.close();
因为这只是覆盖了当前的HTML,当页面刷新时,就不是最初重定向到的那个页面了。
备注:内容来源于stack exchange,提问作者shosholanda

