如何修复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
相关产品推荐
相关产品推荐

