在 POST 路由中的 Flask 中重定向时不允许使用 405 方法
405 Method Not Allowed When Redirecting in Flask within POST route
我希望阐明为什么我会收到 405 方法不允许错误。
预期结果 - 当用户尝试向他们已经添加评论的游戏添加评论时,他们应该被重定向到 manage.html 模板。
实际结果 - 显示 405 错误(方法不允许)。
管理路线:
@app.route('/manage')
def manage():
"""Renders manage.html template."""
return render_template('manage.html')
提交审核路线:
@app.route('/submit_review/<game_id>', methods=['POST'])
def submit_review(game_id):
"""
Add users review to database.
"""
user = User.query.filter_by(username=session['username']).first()
existing_review = Review.query.filter_by(user_id=user.id,
game_id=game.id).first()
if existing_review:
flash('You have already created a review for this game')
return redirect(url_for('manage'))
...
我试过的:
我已经阅读了一些烧瓶文档,特别是关于 flask.redirect
(docs),并搜索了其他示例,但我一直无法找到解决我的问题的东西。
我有一种预感,当用户提交表单时,他们已经对该特定游戏进行了评论,POST 请求也被重定向到“管理”路径。
我检查了开发工具中的网络选项卡,它是一个 GET 请求,它是正确的 URL。
我想我想说的是...我不知道为什么会这样,所以不知道如何寻找解决方案。
网络屏幕截图 -> Headers 开发工具中的选项卡:
服务器控制台:
[10/May/2022 18:43:49] "POST /submit_review/11198 HTTP/1.1" 302 -
[10/May/2022 18:43:49] "review-rating=0&review-heading=&liked-text=&disliked-text=&review-hours=1&game-name=Rocket+League&igdb-id=&igdb-summary=&igdb-cover-url=&action=GET /manage HTTP/1.1" 405 -
当您提交评论时,方法是 POST。然后你重定向到不接受 POST 的页面 /manage。该请求仍然 POST 导致错误。尝试将 POST 方法添加到您的 /manage 装饰器中。
@app.route('/manage', methods= ["GET", "POST"])
def manage():
"""Renders manage.html template."""
return render_template('manage.html')
正如我在您的控制台中看到的那样,您的表单使用了 GET 请求?在这种情况下,您可以使用类似
redirect("/Whereever", code=307)
首先,感谢@Henry 的启发寻找解决方案。
其次,我了解到在原始问题中包含整个功能,而不仅仅是我认为可能相关的功能,可能会更快地解决这个问题。
答案.
@Henry 提到,根据 url_for()
的文档 - “目标端点未知的可变参数作为查询参数附加到生成的 URL。”
这是我对这种情况的看法。
submit_review()
函数在使用表单数据之前返回,这意味着目标端点不知道表单数据。
修复前的函数:
@app.route('/submit_review/<game_id>', methods=['POST'])
def submit_review(game_id):
"""
Adds users review to database.
"""
existing_game = Game.query.filter_by(igdb_id=game_id).first()
if not existing_game:
igdb_game_data = get_game_data_by_id(game_id)[0]
igdb_game_artwork = get_game_artwork(game_id)
igdb_game_cover = get_game_cover_art(game_id)
game = Game(
name=igdb_game_data['name'],
artwork=json.dumps(igdb_game_artwork),
summary=igdb_game_data['summary'],
igdb_id=igdb_game_data['id'],
cover_art=igdb_game_cover
)
db.session.add(game)
db.session.commit()
user = User.query.filter_by(username=session['username']).first()
game = Game.query.filter_by(igdb_id=game_id).first()
existing_review = Review.query.filter_by(user_id=user.id,
game_id=game.id).first()
if existing_review:
print(request)
flash('You have already created a review for this game')
return redirect(url_for('manage'))
review = Review(
user_id=user.id,
game_id=game.id,
rating=float(request.form.get('review-rating')),
heading=request.form.get('review-heading'),
liked_text=request.form.get('liked-text'),
disliked_text=request.form.get('disliked-text'),
hours=int(request.form.get('review-hours')),
)
db.session.add(review)
db.session.commit()
flash('Review added successfully')
return redirect(url_for('home'))
通过移动表单数据的使用位置,我得到了预期的结果,功能是正确的,因为如果存在同一用户对该游戏的评论,评论不会添加到数据库中。
修复后的功能:
@app.route('/submit_review/<game_id>', methods=['POST'])
def submit_review(game_id):
"""
Adds users review to database.
"""
existing_game = Game.query.filter_by(igdb_id=game_id).first()
if not existing_game:
igdb_game_data = get_game_data_by_id(game_id)[0]
igdb_game_artwork = get_game_artwork(game_id)
igdb_game_cover = get_game_cover_art(game_id)
game = Game(
name=igdb_game_data['name'],
artwork=json.dumps(igdb_game_artwork),
summary=igdb_game_data['summary'],
igdb_id=igdb_game_data['id'],
cover_art=igdb_game_cover
)
db.session.add(game)
db.session.commit()
user = User.query.filter_by(username=session['username']).first()
game = Game.query.filter_by(igdb_id=game_id).first()
existing_review = Review.query.filter_by(user_id=user.id,
game_id=game.id).first()
review = Review(
user_id=user.id,
game_id=game.id,
rating=float(request.form.get('review-rating')),
heading=request.form.get('review-heading'),
liked_text=request.form.get('liked-text'),
disliked_text=request.form.get('disliked-text'),
hours=int(request.form.get('review-hours')),
)
if existing_review:
print(request)
flash('You have already created a review for this game')
return redirect(url_for('manage'))
db.session.add(review)
db.session.commit()
flash('Review added successfully')
return redirect(url_for('home'))
我希望阐明为什么我会收到 405 方法不允许错误。
预期结果 - 当用户尝试向他们已经添加评论的游戏添加评论时,他们应该被重定向到 manage.html 模板。
实际结果 - 显示 405 错误(方法不允许)。
管理路线:
@app.route('/manage')
def manage():
"""Renders manage.html template."""
return render_template('manage.html')
提交审核路线:
@app.route('/submit_review/<game_id>', methods=['POST'])
def submit_review(game_id):
"""
Add users review to database.
"""
user = User.query.filter_by(username=session['username']).first()
existing_review = Review.query.filter_by(user_id=user.id,
game_id=game.id).first()
if existing_review:
flash('You have already created a review for this game')
return redirect(url_for('manage'))
...
我试过的:
我已经阅读了一些烧瓶文档,特别是关于 flask.redirect
(docs),并搜索了其他示例,但我一直无法找到解决我的问题的东西。
我有一种预感,当用户提交表单时,他们已经对该特定游戏进行了评论,POST 请求也被重定向到“管理”路径。
我检查了开发工具中的网络选项卡,它是一个 GET 请求,它是正确的 URL。
我想我想说的是...我不知道为什么会这样,所以不知道如何寻找解决方案。
网络屏幕截图 -> Headers 开发工具中的选项卡:
服务器控制台:
[10/May/2022 18:43:49] "POST /submit_review/11198 HTTP/1.1" 302 -
[10/May/2022 18:43:49] "review-rating=0&review-heading=&liked-text=&disliked-text=&review-hours=1&game-name=Rocket+League&igdb-id=&igdb-summary=&igdb-cover-url=&action=GET /manage HTTP/1.1" 405 -
当您提交评论时,方法是 POST。然后你重定向到不接受 POST 的页面 /manage。该请求仍然 POST 导致错误。尝试将 POST 方法添加到您的 /manage 装饰器中。
@app.route('/manage', methods= ["GET", "POST"])
def manage():
"""Renders manage.html template."""
return render_template('manage.html')
正如我在您的控制台中看到的那样,您的表单使用了 GET 请求?在这种情况下,您可以使用类似
redirect("/Whereever", code=307)
首先,感谢@Henry 的启发寻找解决方案。
其次,我了解到在原始问题中包含整个功能,而不仅仅是我认为可能相关的功能,可能会更快地解决这个问题。
答案.
@Henry 提到,根据 url_for()
的文档 - “目标端点未知的可变参数作为查询参数附加到生成的 URL。”
这是我对这种情况的看法。
submit_review()
函数在使用表单数据之前返回,这意味着目标端点不知道表单数据。
修复前的函数:
@app.route('/submit_review/<game_id>', methods=['POST'])
def submit_review(game_id):
"""
Adds users review to database.
"""
existing_game = Game.query.filter_by(igdb_id=game_id).first()
if not existing_game:
igdb_game_data = get_game_data_by_id(game_id)[0]
igdb_game_artwork = get_game_artwork(game_id)
igdb_game_cover = get_game_cover_art(game_id)
game = Game(
name=igdb_game_data['name'],
artwork=json.dumps(igdb_game_artwork),
summary=igdb_game_data['summary'],
igdb_id=igdb_game_data['id'],
cover_art=igdb_game_cover
)
db.session.add(game)
db.session.commit()
user = User.query.filter_by(username=session['username']).first()
game = Game.query.filter_by(igdb_id=game_id).first()
existing_review = Review.query.filter_by(user_id=user.id,
game_id=game.id).first()
if existing_review:
print(request)
flash('You have already created a review for this game')
return redirect(url_for('manage'))
review = Review(
user_id=user.id,
game_id=game.id,
rating=float(request.form.get('review-rating')),
heading=request.form.get('review-heading'),
liked_text=request.form.get('liked-text'),
disliked_text=request.form.get('disliked-text'),
hours=int(request.form.get('review-hours')),
)
db.session.add(review)
db.session.commit()
flash('Review added successfully')
return redirect(url_for('home'))
通过移动表单数据的使用位置,我得到了预期的结果,功能是正确的,因为如果存在同一用户对该游戏的评论,评论不会添加到数据库中。
修复后的功能:
@app.route('/submit_review/<game_id>', methods=['POST'])
def submit_review(game_id):
"""
Adds users review to database.
"""
existing_game = Game.query.filter_by(igdb_id=game_id).first()
if not existing_game:
igdb_game_data = get_game_data_by_id(game_id)[0]
igdb_game_artwork = get_game_artwork(game_id)
igdb_game_cover = get_game_cover_art(game_id)
game = Game(
name=igdb_game_data['name'],
artwork=json.dumps(igdb_game_artwork),
summary=igdb_game_data['summary'],
igdb_id=igdb_game_data['id'],
cover_art=igdb_game_cover
)
db.session.add(game)
db.session.commit()
user = User.query.filter_by(username=session['username']).first()
game = Game.query.filter_by(igdb_id=game_id).first()
existing_review = Review.query.filter_by(user_id=user.id,
game_id=game.id).first()
review = Review(
user_id=user.id,
game_id=game.id,
rating=float(request.form.get('review-rating')),
heading=request.form.get('review-heading'),
liked_text=request.form.get('liked-text'),
disliked_text=request.form.get('disliked-text'),
hours=int(request.form.get('review-hours')),
)
if existing_review:
print(request)
flash('You have already created a review for this game')
return redirect(url_for('manage'))
db.session.add(review)
db.session.commit()
flash('Review added successfully')
return redirect(url_for('home'))