You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask中redirect(url_for())无法实现页面跳转的问题排查

问题描述

提交表单后,服务器返回日志:

> 127.0.0.1 - - [02/Dec/2022 10:37:53] "POST /create-artist HTTP/1.1" 302 -
> 127.0.0.1 - - [02/Dec/2022 10:37:53] "GET /artists-list HTTP/1.1" 200 -

浏览器收到响应,但URL停留在http://localhost:3000/create-artist,未发生跳转。已查阅5个相关问题,未找到匹配情况。

Python后端代码
from flask import Flask, render_template, url_for, redirect, request, abort
from flask_sqlalchemy import SQLAlchemy
import os, sys

db = SQLAlchemy()
app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = URI
db.init_app(app)


##########################################################
#################### CONTROLLERS #########################
##########################################################

# ---------------------------------------------
# ----------------- ARTISTS -------------------
# ---------------------------------------------

@app.route('/artists-list')
def artists_list():
    return render_template('artists.html', data='test')

@app.route('/create-artist', methods = ["GET", "POST"])
def create_artist():
    error = False
    if request.method == "POST":
        try: 
            artist = Artist(
                name = request.get_json()['name'],
                city = request.get_json()['city'],
                state = request.get_json()['state'],
                phone = request.get_json()['phone'],
                genres = request.get_json()['genres'],
            )
            # db.session.add(artist)
            # db.session.commit()
            print(artist)
        except:
            error = True
            # db.session.rollback()
            print(sys.exc_info())
        # finally: 
            # db.session.close()
        if not error:
            return redirect(url_for('artists_list'))
        else: 
            abort(500)


    return render_template('form/create-artist.html')


# --------------- END ARTISTS ------------------


@app.route("/")
def index(): 
    return render_template('home.html')


##########################################################
###################### MODELS ############################
##########################################################


class Artist(db.Model): 
    __tablename__ = 'Artist'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String)
    city = db.Column(db.String(120))
    state = db.Column(db.String(120))
    phone = db.Column(db.String(120))
    genres = db.Column(db.String(120))
    image_link = db.Column(db.String(500))
    facebook_link = db.Column(db.String(120))
HTML前端代码

/create-artist页面

{% extends "artists.html" %}
{% block title %}New artist | Fy-yur{% endblock %}
{% block content %}
<div class="container">
    <h1>This is the create artist page!</h1>
    <form id="artist-form" class="col-md-4">

        <div class="form-group">
            <label for="name">Name</label>
            <input type="text" class="form-control" id="name" placeholder="New Artist">
        </div>

        <div class="form-group">
            <label for="city">City</label>
            <input type="text" class="form-control" id="city" placeholder="Artist's City">
        </div>


        <div class="form-group">
            <label for="state">State</label>
            <select class="form-control" id="state">

            </select>
        </div>
        <div class="form-group">
            <label for="phone">Phone</label>
            <input type="text" class="form-control" id="phone" placeholder="Phone number">
        </div>

        <div class="form-group">
            <label for="genres">Genre</label>
            <select type="text" class="form-control" id="genres">

            </select>
        </div>
        <button type="submit" id="submit" class="btn btn-success">Create</button>
    </form>
</div>

<script>
    document.getElementById('artist-form').onsubmit = e => {
        e.preventDefault();
        const body = {};
        const formData = e.target;
        for (let i = 0; i < formData.length - 1; i++) {
            const currDataKey = formData[i].id;
            const currDataValue = formData[i].value
            body[currDataKey] = currDataValue;
        }
        fetch('/create-artist', {
            method: 'POST',
            body: JSON.stringify(body),
            headers: {
                'Content-Type': 'application/json'
            }
        })
        .then(res => console.log(res))
        .catch(e => console.log(e));
    }
</script>
{% endblock %}

/artists-list页面

{% extends "index.html" %}
{% block title %}Artists | Fy-yur{% endblock %}
{% block content %}
<h1>This is the artists page!</h1>
<div class="container">
    <a href={{ url_for('create_artist') }}>
        <button type="button" class="btn btn-success">
            New artist
        </button>
    </a>
</div>
{% endblock %}
问题原因及解决办法

原因

你通过fetch发起了AJAX请求,服务器返回的302重定向只会被fetch内部处理(所以日志中能看到GET /artists-list的请求),但AJAX请求的重定向不会触发浏览器地址栏变化或页面跳转。

解决办法

方法一:使用表单默认提交方式

删除表单的onsubmit事件处理代码,给表单添加method="POST"和action="/create-artist"属性,让浏览器自动处理重定向:

<form id="artist-form" class="col-md-4" method="POST" action="/create-artist">

同时后端代码要改用request.form获取数据(默认表单提交是application/x-www-form-urlencoded格式,不是JSON):

artist = Artist(
    name = request.form['name'],
    city = request.form['city'],
    state = request.form['state'],
    phone = request.form['phone'],
    genres = request.form['genres'],
)

方法二:保留AJAX并手动处理跳转

在fetch的响应回调中,判断是否为重定向,然后手动跳转页面:

fetch('/create-artist', {
    method: 'POST',
    body: JSON.stringify(body),
    headers: {
        'Content-Type': 'application/json'
    }
})
.then(res => {
    if (res.redirected) {
        window.location.href = res.url;
    } else {
        console.log(res);
    }
})
.catch(e => console.log(e));

或者后端返回JSON格式的跳转指令,前端根据返回值跳转:
后端修改:

from flask import jsonify

# ... 其他代码 ...
if not error:
    return jsonify({'redirect': url_for('artists_list')})

前端修改:

fetch('/create-artist', {
    method: 'POST',
    body: JSON.stringify(body),
    headers: {
        'Content-Type': 'application/json'
    }
})
.then(res => res.json())
.then(data => {
    if (data.redirect) {
        window.location.href = data.redirect;
    }
})
.catch(e => console.log(e));

内容的提问来源于stack exchange,提问作者Martin Carre

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 16:20:35