Я надеюсь пролить свет на то, почему я получаю ошибку 405 Method Not Allowed.
Ожидаемый результат — пользователь должен быть перенаправлен на шаблон 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, особенно по flask.redirect
(документы), и искал другие примеры, но не смог найти что-то, что решило бы мою проблему.
У меня есть подозрение, что когда пользователь отправляет форму и у него уже есть обзор этой конкретной игры, запрос POST также перенаправляется на маршрут «управление».
Я проверил вкладку сети в инструментах разработчика, и это запрос GET, который подходит для этого URL-адреса.
Я думаю, что я пытаюсь сказать... Я понятия не имею, почему это происходит, поэтому не знаю, как искать решение.
Снимок экрана: вкладка «Сеть» -> «Заголовки» в инструментах разработчика:
Консоль сервера:
[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 -
🤔 А знаете ли вы, что...
Python позволяет создавать графические приложения с использованием библиотеки PyQt.
Когда вы отправляете отзыв, используется метод POST. Затем вы перенаправляете на страницу /manage, которая не принимает POST. Запрос по-прежнему 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 за вдохновение для поиска решения.
Во-вторых, я узнал, что включение всей функции в исходный вопрос, а не только то, что, по моему мнению, может иметь значение, могло решить эту проблему намного раньше.
Ответ.
@ Генри упомянул, что в соответствии с документами для 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'))