Flask登录验证通过后无法跳转至admin页面的问题排查
Flask登录跳转失败问题排查
问题现象
运行Flask项目时,用户输入正确的用户名和密码后无法完成页面跳转,登录接口触发路由构建错误。
相关代码
app.py
from flask import Flask, render_template, request, redirect, url_for, session import json,admin,teacher,student,quiz_api from models import Student, Teacher, db, app # from flask import Flask from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) app.secret_key = 'secret_key' app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///quiz.db' db = SQLAlchemy(app) with app.app_context(): db.create_all() # db.create_all() @app.route('/') def index(): return render_template("index.html") @app.route('/login', methods=['POST']) def login(): username = request.form['username'] password = request.form['password'] user_type = request.form['type'] if user_type == 'Teacher': user = Teacher.query.filter_by(username=username).first() if user is None: return "incorrect username" else: if user.password == password: session['username'] = username session['id'] = user.id return redirect(url_for('teacher_index')) else: return "incorrect password" if user_type == 'Admin': if username == 'admin' and password == 'admin': print("inside admin ------") return redirect(url_for('admin')) else: user = Student.query.filter_by(username=username).first() if user is None: return "incorrect username" else: if user.password == password: session['username'] = username session['id'] = user.id return redirect(url_for('student_index')) else: return "incorrect password" @app.route("/logout", methods=['POST']) def logout(): session.pop('username', None) return redirect(url_for('index')) if __name__ == "__main__": app.secret_key = 'super secret key' app.config['SESSION_TYPE'] = 'filesystem' app.debug = True app.run()
admin.py
from flask import render_template, request, redirect, url_for from models import Teacher, Student, Score, Quiz, app, db @app.route('/admin') def admin(): print("hello inside admin") if 'username' == None: return redirect(url_for("index")) teachers = Teacher.query.all() students = Student.query.all() user_data = {'students': students, 'teachers': teachers} print(user_data) return render_template("admin.html", user_data=user_data) @app.route('/delete_student/<student_id>') def delete_student(student_id): student = Student.query.filter_by(id=student_id).first() student_quiz_scores = Score.query.filter_by(student_id=student.id).all() for student_score in student_quiz_scores: db.session.delete(student_score) db.session.commit() db.session.delete(student) db.session.commit() return redirect(url_for('admin')) @app.route('/delete_teacher/<teacher_id>') def delete_teacher(teacher_id): teacher = Teacher.query.filter_by(id=teacher_id).first() # quizes_of_teacher = Quiz.query.filter_by(teacher_id=teacher.id) for quiz in Quiz.query.filter_by(teacher_id=teacher.id): db.session.delete(quiz) db.session.commit() db.session.delete(teacher) db.session.commit() return redirect(url_for('admin')) @app.route('/update_teacher', methods=['POST', 'GET']) def update_teacher(): teacher_id = request.form['t_id'] teacher_username = request.form['t_username'] teacher_password = request.form['t_password'] teacher = Teacher.query.filter_by(id=teacher_id).first() teacher.username = teacher_username teacher.password = teacher_password db.session.commit() return redirect(url_for('admin')) @app.route('/update_student', methods=['POST', 'GET']) def update_student(): student_id = request.form['s_id'] student_username = request.form['s_username'] student_password = request.form['s_password'] student = Student.query.filter_by(id=student_id).first() student.username = student_username student.password = student_password db.session.commit() return redirect(url_for('admin')) @app.route("/insert_teacher", methods=['POST']) def insert_teacher(): name = request.form["teacher_name"] password = request.form["teacher_password"] teacher = Teacher.query.filter_by(username=name).first() if teacher is None: teacher = Teacher(username=name, password=password) db.session.add(teacher) db.session.add(teacher) db.session.commit() return redirect(url_for("admin")) else: return "404 Duplicate Name Error!" @app.route("/insert_student", methods=['POST']) def insert_student(): name = request.form["student_name"] password = request.form["student_password"] student = Student.query.filter_by(username=name).first() if student is None: student = Student(username=name, password=password) db.session.add(student) db.session.commit() return redirect(url_for("admin")) else: return "404 Duplicate Name Error!"
错误日志
inside admin ------ [2024-04-26 22:22:52,567] ERROR in app: Exception on /login [POST] Traceback (most recent call last): File "C:\Users\vatsal\miniconda3\Lib\site-packages\flask\app.py", line 1463, in wsgi_app response = self.full_dispatch_request() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\vatsal\miniconda3\Lib\site-packages\flask\app.py", line 872, in full_dispatch_request rv = self.handle_user_exception(e) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\vatsal\miniconda3\Lib\site-packages\flask\app.py", line 870, in full_dispatch_request rv = self.dispatch_request() ^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\vatsal\miniconda3\Lib\site-packages\flask\app.py", line 855, in dispatch_request return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\temp\Quiz\quiz_management_system_final\app.py", line 43, in login return redirect(url_for('admin')) ^^^^^^^^^^^^^^^^ File "C:\Users\vatsal\miniconda3\Lib\site-packages\flask\helpers.py", line 220, in url_for ^^^^^^^^^^^^^^^^^^^^ File "C:\Users\vatsal\miniconda3\Lib\site-packages\flask\app.py", line 1074, in url_for return self.handle_url_build_error(error, endpoint, values) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ rv = url_adapter.build( # type: ignore[union-attr] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\vatsal\miniconda3\Lib\site-packages\werkzeug\routing\map.py", line 919, in build raise BuildError(endpoint, values, method, self)
问题分析与解决方案
核心问题
错误提示BuildError,说明url_for('admin')找不到对应的路由端点。根源是存在两个独立的Flask应用实例:
app.py中先从models导入了app,但随后又重新创建了app = Flask(__name__),覆盖了导入的实例admin.py中使用的是models里的app实例,其注册的路由没有被当前运行的app.py中的实例识别
修复步骤
统一Flask应用实例
修改app.py,删除重复创建的app和db实例,直接使用从models导入的对象:from flask import Flask, render_template, request, redirect, url_for, session import json,admin,teacher,student,quiz_api from models import Student, Teacher, db, app # 移除以下重复代码 # app = Flask(__name__) # app.secret_key = 'secret_key' # app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///quiz.db' # db = SQLAlchemy(app) with app.app_context(): db.create_all() # 后续代码保持不变...修复admin.py中的登录校验逻辑
admin视图中的if 'username' == None逻辑错误,应该检查session中是否存在username:@app.route('/admin') def admin(): print("hello inside admin") if 'username' not in session: # 修正此处 return redirect(url_for("index")) # 后续代码保持不变...修复admin.py中的重复添加数据问题
insert_teacher函数中重复执行了db.session.add(teacher),删除其中一条:@app.route("/insert_teacher", methods=['POST']) def insert_teacher(): name = request.form["teacher_name"] password = request.form["teacher_password"] teacher = Teacher.query.filter_by(username=name).first() if teacher is None: teacher = Teacher(username=name, password=password) db.session.add(teacher) # 移除重复的db.session.add(teacher) db.session.commit() return redirect(url_for("admin")) else: return "404 Duplicate Name Error!"确保子模块路由被正确注册
保证admin.py、teacher.py等模块在app.py启动前被导入,这样它们的路由才能注册到统一的app实例上。当前app.py已经导入了admin,这部分没问题。
完成以上修改后,重新启动项目,登录admin账号即可正常跳转。
内容的提问来源于stack exchange,提问作者vatsal mangukiya
相关产品推荐
相关产品推荐

