Flask 视图函数在 GET 请求后发送 POST 请求时丢失请求参数
Flask view function losing request arguments when sending a POST request after GET request
此视图在发出 GET 请求时接收 ?next= 参数,但一旦用户向同一视图发出 POST 请求,该参数就会丢失。我看到的示例没有明确传递查询参数,但似乎能够保留它们并在以下 POST 请求中获取它们。
@blueprint.route("/login", methods=["GET", "POST"])
@logout_required()
def login():
form = LoginForm()
#1
print("NEXT:", request.args.get("next"))
if form.validate_on_submit():
u = User.query.filter_by(username=form.username.data).first()
if u and u.check_password(password=form.password.data):
if u.is_active():
#2
print("NEXT:", request.args.get("next"))
login_user(u, remember=form.remember.data)
next_url = request.args.get("next")
if not next_url or url_parse(next_url).netloc != "":
next_url = url_for("main.index")
return redirect(next_url)
else:
flash("This account has been disabled", "error")
else:
flash("Invalid password or username.", "error")
return render_template("auth/login.html", form=form)
在最后两个 flash()
函数之后,您缺少 return redirect()
的两个重定向,请参阅下面的代码:
@blueprint.route("/login", methods=["GET", "POST"])
@logout_required()
def login():
form = LoginForm()
#1
print("NEXT:", request.args.get("next"))
if form.validate_on_submit():
next_url = request.args.get("next") # -- HERE -- get "?next argument"
u = User.query.filter_by(username=form.username.data).first()
if u and u.check_password(password=form.password.data):
if u.is_active():
#2
print("NEXT:", request.args.get("next"))
login_user(u, remember=form.remember.data)
# next_url = request.args.get("next") # -- HERE --
if not next_url or url_parse(next_url).netloc != "":
next_url = url_for("main.index")
return redirect(next_url)
else:
flash("This account has been disabled", "error")
return redirect(url_for('auth.index')) # -- HERE --
else:
flash("Invalid password or username.", "error")
return redirect(url_for('auth.login', next=next_url)) # -- HERE --
return render_template("auth/login.html", form=form)
我假设 /main
是受保护的路由并且当前没有会话,用户 尚未登录 ,所以当用户尝试 直接访问
http://localhost:5000/admin
他将被自动重定向到此 url
(auth.login
带有参数 ?next=%2Fadmin%2F
的路由)
http://localhost:5000/auth/login?next=%2Fadmin%2F
使用默认flask-login
flash()
消息Please log in to access this page.
然后他可以登录,如果登录成功他将登录并重定向到保护区使用?next
参数,
但是如果它发生了并且诱惑失败了,我们有两个选择:
如果 Invalid password or username
他将被重定向 auth.login
路线 with ?next=%2Fadmin%2F
第二次机会。
但是如果 This account has been disabled
他将被重定向到 auth.login
路由 而没有 ?next=%2Fadmin%2F
参数并且它确实有意义.
最后你不需要担心 ?next=
的值,因为用户可以玩它甚至删除它和这个块
if not next_url or url_parse(next_url).netloc != "":
next_url = url_for("main.index")
return redirect(next_url)
默认为 main.index
(如果有)。
发现问题基本上是因为我将 GET 请求参数与 POST 输入提交混合在一起。
我的登录 url http://localhost:8000/auth/login?next=%2Fadmin
<form action="">
将向登录视图函数发送 POST 请求并允许通过 request.args.get()
访问
然而,捕获和传递 GET 请求 next
参数的正确方法是通过一个隐藏的输入字段,该字段包含初始 GET 请求的 next
参数,允许它正确传递作为 POST 请求中表单的一部分。
<form action="{{ url_for('auth.login' }}">
<input id="next" name="next" type="hidden" value="/admin">
视图函数:
@blueprint.route("/login", methods=["GET", "POST"])
@logout_required()
def login():
form = LoginForm(next=request.args.get("next"))
此视图在发出 GET 请求时接收 ?next= 参数,但一旦用户向同一视图发出 POST 请求,该参数就会丢失。我看到的示例没有明确传递查询参数,但似乎能够保留它们并在以下 POST 请求中获取它们。
@blueprint.route("/login", methods=["GET", "POST"])
@logout_required()
def login():
form = LoginForm()
#1
print("NEXT:", request.args.get("next"))
if form.validate_on_submit():
u = User.query.filter_by(username=form.username.data).first()
if u and u.check_password(password=form.password.data):
if u.is_active():
#2
print("NEXT:", request.args.get("next"))
login_user(u, remember=form.remember.data)
next_url = request.args.get("next")
if not next_url or url_parse(next_url).netloc != "":
next_url = url_for("main.index")
return redirect(next_url)
else:
flash("This account has been disabled", "error")
else:
flash("Invalid password or username.", "error")
return render_template("auth/login.html", form=form)
在最后两个 flash()
函数之后,您缺少 return redirect()
的两个重定向,请参阅下面的代码:
@blueprint.route("/login", methods=["GET", "POST"])
@logout_required()
def login():
form = LoginForm()
#1
print("NEXT:", request.args.get("next"))
if form.validate_on_submit():
next_url = request.args.get("next") # -- HERE -- get "?next argument"
u = User.query.filter_by(username=form.username.data).first()
if u and u.check_password(password=form.password.data):
if u.is_active():
#2
print("NEXT:", request.args.get("next"))
login_user(u, remember=form.remember.data)
# next_url = request.args.get("next") # -- HERE --
if not next_url or url_parse(next_url).netloc != "":
next_url = url_for("main.index")
return redirect(next_url)
else:
flash("This account has been disabled", "error")
return redirect(url_for('auth.index')) # -- HERE --
else:
flash("Invalid password or username.", "error")
return redirect(url_for('auth.login', next=next_url)) # -- HERE --
return render_template("auth/login.html", form=form)
我假设 /main
是受保护的路由并且当前没有会话,用户 尚未登录 ,所以当用户尝试 直接访问
http://localhost:5000/admin
他将被自动重定向到此 url
(auth.login
带有参数 ?next=%2Fadmin%2F
的路由)
http://localhost:5000/auth/login?next=%2Fadmin%2F
使用默认flask-login
flash()
消息Please log in to access this page.
然后他可以登录,如果登录成功他将登录并重定向到保护区使用?next
参数,
但是如果它发生了并且诱惑失败了,我们有两个选择:
如果
Invalid password or username
他将被重定向auth.login
路线 with?next=%2Fadmin%2F
第二次机会。但是如果
This account has been disabled
他将被重定向到auth.login
路由 而没有?next=%2Fadmin%2F
参数并且它确实有意义.
最后你不需要担心 ?next=
的值,因为用户可以玩它甚至删除它和这个块
if not next_url or url_parse(next_url).netloc != "":
next_url = url_for("main.index")
return redirect(next_url)
默认为 main.index
(如果有)。
发现问题基本上是因为我将 GET 请求参数与 POST 输入提交混合在一起。
我的登录 url http://localhost:8000/auth/login?next=%2Fadmin
<form action="">
将向登录视图函数发送 POST 请求并允许通过 request.args.get()
然而,捕获和传递 GET 请求 next
参数的正确方法是通过一个隐藏的输入字段,该字段包含初始 GET 请求的 next
参数,允许它正确传递作为 POST 请求中表单的一部分。
<form action="{{ url_for('auth.login' }}">
<input id="next" name="next" type="hidden" value="/admin">
视图函数:
@blueprint.route("/login", methods=["GET", "POST"])
@logout_required()
def login():
form = LoginForm(next=request.args.get("next"))