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

如何修复Flask中的循环导入及auth_routes接口CORS问题?

问题

我是Flask和Python新手,在auth_routes与user路由间遇到循环导入问题,除auth_routes的signup、login接口外,其他API端点均可正常访问。使用Postman测试这两个接口失败,前端调用signup时出现CORS报错:

signup:1 Access to XMLHttpRequest at 'http://localhost:8080/signup' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

文件结构

app/
    |backend/
        |models/
            |user.py
            |etc...
        |routes/
            |auth_routes.py
            |etc...
        |app.py
    |frontend/
        ...

auth_routes从app和models.user导入,user.py从app导入db。

auth_routes代码

from flask import Blueprint, request, jsonify, abort
from flask_login import login_user, logout_user, login_required
from werkzeug.security import generate_password_hash, check_password_hash
import jwt
from datetime import datetime, timedelta
from app import db, app
from models import User

auth_routes = Blueprint('auth_routes', __name__)

@auth_routes.route('/signup', methods=['POST'])
def signup():
  print(request)
  data = request.get_json()
  print(data)

  user_exists = User.query.filter_by(email=data['email']).first()

  if user_exists:
    abort(400)

  if len(data['password']) < 8:
    return jsonify({'message': 'Password must be at least 8 characters long'}), 400

  hashed_password = generate_password_hash(data['password'], method='sha256')
  
  new_user = User(email=data['email'], password=hashed_password, 
            first_name=data['first_name'], last_name=data['last_name'])
  
  db.session.add(new_user)
  db.session.commit()
  
  return jsonify({'message': 'User registered successfully'}), 201

@auth_routes.route('/login', methods=['POST'])
def login():
  data = request.get_json()
  user = User.query.filter_by(email=data['email']).first()
  
  if user and check_password_hash(user.password, data['password']):
    token = jwt.encode({
      'user_id': user.id,
      'exp': datetime.utcnow() + timedelta(days=1)
    }, app.config['SECRET_KEY'], algorithm='HS256')
    
    return jsonify({'token': token})
  
  return jsonify({'message': 'Invalid credentials'}), 401

app.py代码

from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_cors import CORS
from functools import wraps
import jwt

from routes.auth_routes import auth_routes
from routes.user_routes import user_routes
from routes.event_routes import event_routes
from routes.artist_routes import artist_routes
from routes.venue_routes import venue_routes
from routes.genre_routes import genre_routes

from models.user import User

app = Flask(__name__)
CORS(app, origins=["http://localhost:3000"], method=["GET", "POST", "PUT", "DELETE"], allow_headers=["Content-Type", "Authorization"])
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:password@localhost/ticketmaster_clone'
app.config['SECRET_KEY'] = 'secretkey'

def token_required(f):
  @wraps(f)
  def decorated(*args, **kwargs):
    token = request.headers.get('Authorization')
    if not token:
      return jsonify({'message': 'Token is missing'}), 401
    try:
      data = jwt.decode(token, app.config['SECRET_KEY'], algorithms=['HS256'])
      current_user = User.query.get(data['user_id'])
    except:
      return jsonify({'message': 'Token is invalid'}), 401
    return f(current_user, *args, **kwargs)
  return decorated


db = SQLAlchemy(app)
app.register_blueprint(auth_routes)
app.register_blueprint(user_routes)
app.register_blueprint(event_routes)
app.register_blueprint(artist_routes)
app.register_blueprint(venue_routes)
app.register_blueprint(genre_routes)

migrate = Migrate(app, db)

if __name__ == '__main__':
  app.run(debug=True, port=8080)

解决方法

1. 修复循环导入问题

当前循环导入的核心原因是初始化顺序错误:app.py先导入路由和模型,但此时db对象还未创建,导致依赖链断裂。

修正步骤:

  • 调整app.py的代码顺序:先初始化db,再导入模型和路由
  • auth_routes中改用current_app获取配置,避免直接导入未初始化的app对象

修改后的app.py关键片段:

app = Flask(__name__)
CORS(app, origins=["http://localhost:3000"], methods=["GET", "POST", "PUT", "DELETE"], allow_headers=["Content-Type", "Authorization"])
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:password@localhost/ticketmaster_clone'
app.config['SECRET_KEY'] = 'secretkey'

# 先初始化db,再导入依赖db的模型和路由
db = SQLAlchemy(app)
from models.user import User
from routes.auth_routes import auth_routes
from routes.user_routes import user_routes
# 其他路由导入...

# 注册蓝图
app.register_blueprint(auth_routes)
# 其他蓝图注册...

修改后的auth_routes.py导入和login函数:

from flask import Blueprint, request, jsonify, abort, current_app  # 添加current_app
from flask_login import login_user, logout_user, login_required
from werkzeug.security import generate_password_hash, check_password_hash
import jwt
from datetime import datetime, timedelta
from app import db  # 仅导入db
from models.user import User  # 明确导入User

auth_routes = Blueprint('auth_routes', __name__)

# login函数中替换app为current_app
@auth_routes.route('/login', methods=['POST'])
def login():
  data = request.get_json()
  user = User.query.filter_by(email=data['email']).first()
  
  if user and check_password_hash(user.password, data['password']):
    token = jwt.encode({
      'user_id': user.id,
      'exp': datetime.utcnow() + timedelta(days=1)
    }, current_app.config['SECRET_KEY'], algorithm='HS256')
    
    return jsonify({'token': token})
  
  return jsonify({'message': 'Invalid credentials'}), 401

2. 修复CORS配置错误

当前CORS配置的method参数拼写错误(应为复数methods),导致OPTIONS预请求无法被正确处理,触发CORS报错。

修正后的CORS配置:

CORS(app, origins=["http://localhost:3000"], methods=["GET", "POST", "PUT", "DELETE"], allow_headers=["Content-Type", "Authorization"])

3. 修复接口错误返回逻辑

signup接口中abort(400)会返回HTML错误页面,而非JSON格式,导致前端解析失败且预请求状态异常,需替换为JSON返回:

if user_exists:
    return jsonify({'message': 'User already exists'}), 400

额外检查点

  • Postman测试时,确保请求头包含Content-Type: application/json,且请求体为合法JSON格式
  • 确认user.py模型正确继承db.Model,并定义了email、password、first_name、last_name等字段

内容的提问来源于stack exchange,提问作者David Chan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 08:30:02