☰
Python Flask与MySQL从入门到实战:学生管理系统部署与避坑指南
2026/10/7 3:13:52 网站建设 项目流程

简介:基于Python+Flask+MySQL开发的学生管理系统项目包,专门面向毕业设计、期末大作业及课程设计场景。项目采用Flask轻量级框架搭建后端,MySQL作为数据存储,前端由HTML/CSS/JS页面构成,涵盖学生信息管理、数据增删改查等常见功能模块。整体代码结构清晰,关键位置包含注释,即使基础薄弱的新手也能较快读懂项目逻辑;配合文档说明与数据库脚本,下载后完成简单部署即可运行。压缩包共32个文件,包含9个HTML页面、8个CSS样式、7个JS脚本、2个Python源文件、2个Markdown文档、1个SQL数据库脚本及配置文件等,整体大小约840KB。前端页面与后端逻辑分离,便于按目录定位修改;SQL文件可直接导入MySQL,省去手动建表步骤。目前已有364人学习下载。这份高分项目源码可作为课程作业或毕设的完整参考,既展示了Flask+MySQL的典型开发流程,也能帮助理解前后端数据交互、路由设计与数据库操作等核心知识点。

1. 学生管理系统:Flask + MySQL 的毕业设计,值不值得拿来做

如果你正在搜“学生管理系统 python 源码”,大概率是在赶毕设,或者在期末大作业的最后两周里挣扎。网上这类资源很多,一搜一大把,但真正能跑起来、表结构建得完整、还愿意把数据库脚本一并给你的,并不多。这套基于 Python + Flask 框架 + MySQL 数据库的学生管理系统,恰好属于那种“三件套齐全”的项目:源码、文档说明、数据库脚本都在包里。它能解决的核心问题不是展示某个炫技功能,而是把登录、学生信息管理、班级管理等一条完整业务链路走通,适合用来做毕业设计或期末大作业的底子。下面我会按选型逻辑、部署过程、源码拆解、踩坑记录这个顺序把它过一遍,照着做比你自己从零写快得多。

2. 为什么选 Flask + MySQL:技术栈拆解与选型逻辑

2.1 Flask 对比 FastAPI 和 Django:毕设场景下谁更合适

一个很常见的纠结是:Python 做 Web 后端,到底选 Flask、Django 还是 FastAPI?三种框架本身没有绝对优劣,但放在毕设和期末大作业这个特定场景里,区别非常明显。我从四个维度把它们摆在一起看。

对比维度FlaskDjangoFastAPI
上手成本低,几行代码起一个服务高,要理解 app、settings、ORM、admin 一堆概念中,路由写法简单但有异步门槛
自带功能只有路由和基础请求处理,扩展自己选全家桶,admin 后台、ORM、表单都内置自动生成 OpenAPI 文档,自带数据校验
中文资料非常多,中文社区积累厚很多相对少,且偏新
答辩友好度容易把请求响应、会话、蓝图讲清楚容易被问“框架做了多少、你做了什么”容易陷入 async 和同步数据库连接的纠缠

我的看法是:毕设场景选 Flask,不是因为“它比 FastAPI 更先进”,而是因为它边界清楚。你用蓝图把登录、学生管理、班级管理拆开,每一块都能对应到课本里的 HTTP 基础。用 FastAPI 写异步路由,第一次接触的人很容易在 async 和同步 MySQL 连接器之间分心;用 Django 则有一种“我用框架做了个后台”的错觉,老师一旦追问中间件执行顺序,很多人直接卡住。而且 Flask 的报错信息相对直白,近几年的学生管理系统源码大部分也是 Flask 写的,遇到问题一搜就有答案。这套资源本身就是 Flask 实现,直接进入业务逻辑,没必要再从框架选型开始造轮子。

2.2 MySQL 在项目里的角色:为什么不用 SQLite

Flask 默认带一个非常简单的关系型数据库 SQLite,但我在拆这种课设项目时,会明确建议换成 MySQL。SQLite 是单文件数据库,适合原型阶段、适合表结构还没想清楚的场景,但放在毕设里有三个问题:第一,老师问“你的数据存在哪里”,你说一个文件,说服力不够;第二,你在本机跑得好好的,换一台机器演示时文件路径和权限容易出问题;第三,你很难在文档里写出一段像样的“环境配置过程”。

MySQL 恰恰相反,你可以在文档里正大光明写:安装 MySQL、配置 root 密码、用 Navicat 或命令行导入 student.sql。这个过程本身就是课程里的知识点,写到说明文档里是加分项。Windows 10 上的 MySQL 安装配置教程网上非常多,你自己装一遍,顺便把踩过的坑写进文档,整套项目的完整度会高不少。从实际答辩角度看,老师对学生管理系统这种题目的预期,就是“数据库用 MySQL,后台用 Python Web 框架”。用 SQLite 做演示,反而容易让老师觉得你没有按主流工程习惯来。

Flask 连接 MySQL 有两条常见路线:一条是用 Flask-SQLAlchemy 扩展,把表映射成模型类,代码里操作对象;另一条是直接用 PyMySQL 写原生 SQL,连接、游标、执行、提交。这套资源里如果给的是原生 SQL 写法,调试时可以直接把语句复制到 Navicat 里跑一遍;如果用的是 ORM,也可以接受,但你要能看懂它最终生成的 SQL。无论哪种路线,项目里有一个 .sql 脚本都是最省事的事情,你不用手工建表,执行一次导入,表结构、初始管理员账号、示例数据就都齐了。导入前确认 MySQL 服务是启动状态,建库时指定 utf8mb4 字符集,否则后面中文乱码的坑大概率逃不掉。

2.3 这类系统的功能边界:和选课系统的差别在哪里

学生管理系统听起来范围很大,但落到具体课设上,功能边界一般是固定的:管理员登录、首页仪表盘、学生信息增删改查、班级管理、搜索分页。可能还会带一个简单的教师或成绩模块。这些功能统称 CRUD 闭环,看起来不起眼,但它恰好覆盖了“前端表单提交 + 后端路由接收 + 数据库读写 + 页面回显”这条完整链路。

它和学生选课管理系统最大的区别是表结构复杂度。选课系统至少要有一张选课关系表,把学生表和课程表通过外键关联起来,还得做冲突检测、退课、成绩录入,数据模型至少多两层关联。学生管理系统只需要把“人”和“组织”的关系维护好,比如一个班级对应多个学生,一个管理员管理全部数据。这也是这套源码的价值所在:它把登录权限、增删改查、分页搜索都做了,又没有冗余到你读不懂。答辩时你讲“这是我的核心表结构,学生表和班级表通过 class_id 关联”,比讲“我调用了某个第三方接口”更有说服力。如果你后面想扩展成选课系统,只需要加一张选课记录表再加两个路由,底子不用推翻重来。

3. 把项目跑起来:环境配置、依赖安装与启动流程

3.1 Python 环境准备:版本选择与虚拟环境

在跑源码之前,先把 Python 环境收拾干净。Python 3.8 到 3.10 这个区间对 Flask 和 PyMySQL 最友好,不建议用太新的版本,有些依赖可能还没跟上。安装 Python 时有一个细节非常关键:安装界面底部那个 Add Python to PATH 一定要勾上,不然后面命令行里执行 python 会提示“不是内部或外部命令”。这一步卡住的人非常多,而且完全和项目源码没关系。

装好 Python 后,在项目根目录打开终端创建虚拟环境:

# 创建虚拟环境 python -m venv venv # Windows 激活 venv\Scripts\activate # Linux / macOS 激活 source venv/bin/activate # 确认当前解释器路径 where python # Windows 下执行 which python # Linux/macOS 下执行

逻辑说明:venv是 Python 自带的虚拟环境模块,作用是给这个项目隔离出一份独立的第三方包环境,后面用 pip 安装的 Flask、PyMySQL 都装进 venv 目录里,不会和系统里其他项目互相污染。参数说明:激活后命令行提示符前面会出现 (venv) 标志,这时 where python 显示的路径应该在当前项目的 venv 目录下。如果路径不对,说明激活失败;Windows 下如果报“禁止运行脚本”,在管理员 PowerShell 里执行Set-ExecutionPolicy RemoteSigned再重新激活即可。

3.2 安装依赖并导入数据库脚本

激活虚拟环境后,安装项目依赖。资源包里如果带 requirements.txt,直接一条命令装完:

# 激活虚拟环境后执行 pip install -r requirements.txt

如果包里没给 requirements.txt,按这套项目最常用的组合手动装:

pip install flask pymysql flask-sqlalchemy

逻辑说明:这份项目依赖清单里至少有 Flask 本身、MySQL 驱动、以及可能用到的 ORM 扩展。flask-sqlalchemy是 ORM 扩展,像 4.3 节里那种分页查询就是靠它简化操作;PyMySQL 负责让 Python 能和 MySQL 直接对话,没有它,Flask 不知道往哪个数据库写数据。接着把数据库脚本导入 MySQL,命令行和图形工具两种方式都可以:

# 命令行方式:先登录 mysql -u root -p -h 127.0.0.1 -P 3306 # 登录后执行 CREATE DATABASE student_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE student_db; SOURCE D:/project/student.sql;
# 或者一条命令直接导入 mysql -u root -p student_db < D:/project/student.sql

参数说明:-u root是用户名,-p表示提示输入密码,-h 127.0.0.1指定本地地址,-P 3306指定端口,默认就是 3306。最后一行我把 SQL 文件路径写成了正斜杠,Windows 下反斜杠路径在命令行里有时会出现转义问题,正斜杠更稳。导入完成后可以执行SHOW TABLES;查看是否生成了学生表、班级表、管理员表。如果你在 Windows 上安装 MySQL 时没把 bin 目录加入 PATH,命令行会提示找不到 mysql 命令,需要先到安装目录执行,或者手动加环境变量。还有一种常见情况是 Docker 安装 MySQL 失败,日志里提示端口被占用或者权限不够,那就先检查 3306 端口映射,再决定重新创建容器还是直接换本机安装。

数据库就绪后,改配置。项目里的数据库连接配置一般集中在 config.py:

# config.py import pymysql DB_HOST = "127.0.0.1" DB_PORT = 3306 DB_USER = "root" DB_PASSWORD = "改成你自己的密码" DB_NAME = "student_db" # 如果项目用 PyMySQL 直连,这里就是连接串 DB_URI = f"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}?charset=utf8mb4" # Flask 的 session 需要 SECRET_KEY SECRET_KEY = "换成一串随机字符"

逻辑说明:连接串里的mysql+pymysql://是 SQLAlchemy 认识的方言格式,意思是用 pymysql 这个驱动去连 mysql;后面?charset=utf8mb4是 URL 查询参数,强制连接使用 utf8mb4 字符集,这是防止中文乱码的第一道防线。SECRET_KEY 是给 session 签名用的,如果你不改成自己的字符串,别人可能猜到默认值,存在安全风险,答辩前一定要换。参数说明:如果你的密码里包含 @、#、? 这类特殊字符,直接拼到连接串里会解析错位,需要先用urllib.parse.quote对密码做编码,这是很多老手也会踩的坑。

3.3 启动 Flask 应用与首次访问验证

环境全部就绪后,启动项目:

# 激活虚拟环境 python app.py

如果项目采用的是工厂模式,入口文件可能是 run.py 或 wsgi.py,那启动命令就是python run.py。正常情况下终端会打印Running on http://127.0.0.1:5000,浏览器打开这个地址,就能看到登录页面。默认管理员账号密码一般写在文档说明里,或者写在 student.sql 脚本的文件头注释里,常见的是 admin / 123456,如果你是自己导入的脚本,以脚本里的 INSERT 语句为准。

关于启动方式,一个提醒:开发时用app.run(debug=True),改代码会自动重载,方便调试;但答辩前要把 debug 关掉,因为开着 debug 一旦页面报错,异常堆栈会直接显示在浏览器上,老师看到大量红字印象分会打折。常见做法是:

# 入口文件尾部 if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, debug=False)

逻辑说明:host="0.0.0.0"表示监听所有网络接口,这样同一局域网内其他设备也能访问,答辩时你带一台备用笔记本或者让老师用手机扫码查看都方便。Windows 防火墙通常会在第一次监听时弹窗询问是否允许 Python 通过,一定要点允许,否则别人访问会超时。参数说明:port=5000是 Flask 默认端口,如果被占用就换 5001,后面第 5 章会专门讲端口冲突的排查方法。

4. 读懂这套源码:核心模块、请求流程与二次开发切入点

4.1 目录结构与蓝图组织

项目跑通之后,一定要把目录结构过一遍。因为你答辩时大概率会被问到“你的代码是怎么组织的”。一个典型的 Flask 课设目录长这样:

student-manager/ ├── app.py # 入口文件:创建 app、注册蓝图 ├── config.py # 数据库连接与 Flask 配置 ├── requirements.txt # 依赖清单 ├── student.sql # 数据库脚本:表结构 + 初始数据 ├── models.py # 数据模型或数据库操作封装 ├── views/ # 蓝图目录 │ ├── auth.py # 登录、注销 │ ├── student.py # 学生信息增删改查 │ └── dashboard.py # 首页统计 ├── templates/ # Jinja2 模板 │ ├── login.html │ └── student/ │ ├── list.html │ └── edit.html └── static/ # 静态资源 ├── css/ style.css └── js/ main.js

如果你在入口文件里看到app.register_blueprint(auth_bp),说明这套源码用了 Flask 蓝图。蓝图的作用是把不同业务模块的路由拆到各自文件里,避免 app.py 越写越长。这也是一个很加分的答辩提问点。当老师问“为什么要用蓝图”,你可以回答:登录和学生管理是两个独立的业务域,拆开以后每个文件职责单一,路由冲突也会在注册时就被发现。这个答案比“大家都这么写”好得多,因为你是从工程组织角度解释的。

4.2 登录认证、会话与密码加密

登录模块是这套系统里最重要的安全点。很多低质量的源码把密码明文存进数据库,答辩时被老师抓到直接扣分。规范的写法是用哈希函数处理密码。下面这段是常见的登录路由结构,你可以对照着看源码里是不是同样的套路:

# views/auth.py(示例结构) from flask import Blueprint, render_template, request, redirect, session, url_for from werkzeug.security import check_password_hash from models import get_user_by_username auth_bp = Blueprint("auth", __name__) @auth_bp.route("/login", methods=["GET", "POST"]) def login(): if request.method == "POST": username = request.form.get("username") password = request.form.get("password") user = get_user_by_username(username) # 密码比对:数据库存的是哈希值,不是明文 if user and check_password_hash(user["password_hash"], password): session["uid"] = user["id"] session["username"] = user["username"] session["role"] = user["role"] return redirect(url_for("dashboard.index")) return render_template("login.html", error="用户名或密码错误") return render_template("login.html")

逻辑说明:登录成功后,代码没有把密码放进 session,而是只存了 uid、username 和 role。session 本身是服务端签名的 cookie,后续每个请求都能从 session 里读取当前用户身份。注册用户时,源码里一般会调用generate_password_hash(password)生成哈希值再存入数据库,所以管理员即使打开数据库也看不到用户的真实密码。参数说明:methods=["GET", "POST"]必须两个都写,首次访问登录页是 GET,点提交是 POST;如果只写 GET,表单提交会报 405。url_for("dashboard.index")是反向解析路由,不要手写/dashboard这种路径,因为蓝图加上前缀或改名后手写路径很容易失效。

4.3 学生信息管理核心链路:查询、分页与删除

学生列表页是这套系统的主战场,它的核心是查询与分页。看一下常见的列表路由结构:

# views/student.py(示例结构) from flask import Blueprint, request, render_template, redirect, url_for from models import get_students_page, delete_student_by_id student_bp = Blueprint("student", __name__) @student_bp.route("/student/list") def student_list(): # request.args.get 拿的是 URL 查询参数,比如 /student/list?page=2&keyword=张 page = int(request.args.get("page", 1)) keyword = request.args.get("keyword", "").strip() per_page = 10 # 分页查询:返回总数和当前页数据 total, rows = get_students_page(page, per_page, keyword) total_pages = (total + per_page - 1) // per_page return render_template("student/list.html", rows=rows, total=total, page=page, total_pages=total_pages, keyword=keyword) @student_bp.route("/student/<int:student_id>/delete", methods=["POST"]) def student_delete(student_id): delete_student_by_id(student_id) return redirect(url_for("student.student_list"))

逻辑说明:分页公式(total + per_page - 1) // per_page是向上取整,总记录数正好是 10 的倍数时不会多出空页。删除操作用的是 POST 而不是 GET,因为 GET 的 URL 会被浏览器预加载、被历史记录留存,一个不留神就把数据删了。用 POST 提交删除是工程里的标准做法,很多课设源码在这里用 GET,答辩时是最容易被挑刺的位置。参数说明:<int:student_id>是 Flask 路由转换器,它保证 URL 里 student_id 不是数字时直接返回 404,根本不会进数据库查询。request.args.get("page", 1)的第二个参数是默认值,URL 里没带 page 参数时返回第 1 页。

如果这套源码用的是 SQLAlchemy,那get_students_page内部大概率是链式查询加paginate(),最终生成的 SQL 和原生写法的逻辑一致。查询结果要按时间或学号排序的话,原生 SQL 就写ORDER BY id DESC,ORM 就写.order_by(Student.id.desc())。MySQL 里排序默认是升序,写 DESC 才是倒序,手写 SQL 时这是最容易错的地方。再提一个隐蔽问题:原生 SQL 写错了直接把语句复制到 Navicat 里跑一遍就知道哪里报错;ORM 写法的坑在于模型属性名和数据库字段名可能不一致,比如数据库字段是 created_at,模型里却写 create_time,查询不报错但拿到的值是空的。遇到这种问题,先把 ORM 打印出来的 SQL 和数据库表结构逐列对照。

5. 避坑清单:Flask + MySQL 部署里的五个高频翻车现场

5.1 中文乱码:页面里全是问号

现象:登录后学生列表里的中文显示为??,或者往数据库里插一条中文记录,再查出来全是问号。

原因:MySQL 建库时用了默认字符集 latin1,或者导入 SQL 脚本时客户端和服务器字符集不一致,也可能连接串里没指定 charset。

解决:按第 3 章的语句删库重建,建库时显式写DEFAULT CHARACTER SET utf8mb4;导入脚本前先执行SET NAMES utf8mb4;连接串里加?charset=utf8mb4。如果数据已经存成问号,通常建议别手工 UPDATE,直接把脚本重新导入一次更省事,因为问号本身说明 SQL 脚本里的中文在导入时已经按错误编码解析,回不去了。另外提一句:用记事本打开 SQL 脚本查看中文时,如果看到一堆乱码,说明文件本身编码不对,用 VSCode 或 Notepad++ 把编码切成 UTF-8 重新保存再导入。

5.2 MySQL 连接失败:1045、2003 和 Access denied

现象:启动项目后页面报MySQL Connection not available,命令行执行连接时报ERROR 1045 (28000): Access denied for user 'root'@'localhost',或者ERROR 2003: Can't connect to MySQL server on '127.0.0.1:3306'。

原因:1045 是用户名或密码不对,2003 是 MySQL 服务没启动、端口不对或者防火墙拦了。

解决:先确认 MySQL 服务状态。Windows 下按 Win+R 输入 services.msc,找到 MySQL 服务看是否在运行;如果安装的是 MySQL 5.7.44 但服务名带端口号,说明你可能装成了自定义实例。再确认账号密码,本机演示直接用 root 连,密码必须在 config.py 和 MySQL 实际密码之间保持一致。最后确认端口,安装 MySQL 时如果你手滑把端口改成了 3307,连接自然失败。Docker 安装 MySQL 失败时同样先看日志,docker logs 容器名会直接告诉你是端口冲突还是权限问题。在本地永远先把服务状态、端口、账号三项查完再动代码。

5.3 Flask 端口被占用:启动报 Address already in use

现象:执行 python app.py 后终端直接报OSError: [Errno 98] Address already in use,Windows 下是OSError: [WinError 10013]。另一种情况是浏览器打开 127.0.0.1:5000 显示的不是你这个项目。

原因:上一次启动的 Flask 进程没有真正退出。PyCharm 里点了 Stop 后后台进程有时仍然活着,尤其是用调试模式时会拉起一个 reloader 子进程,单独杀主进程杀不干净。

解决:Windows 下先查端口占用:

netstat -ano | findstr 5000

输出的最后一列就是进程 PID,然后强制结束:

taskkill /PID 这里换成PID数字 /F

临时调试也可以直接用app.run(port=5001)换个端口看页面,但只是应急,别养成习惯。为了方便,我一般会在项目里写一个stop.bat,内容就是查端口杀进程,演示前跑一遍,省得现场翻车。

5.4 TemplateNotFound 或静态文件 404

现象:登录成功后跳转时报jinja2.exceptions.TemplateNotFound: student/list.html,或者页面能打开但完全没有样式,F12 里全是 CSS 404。

原因:模板路径不对是第一种,render_template("student/list.html")里的字符串和 templates 目录下实际文件名不一致;第二种是 templates 文件夹没有放在项目根目录,Flask 默认只从 app 同级目录下找 templates;第三种是文件大小写不一致,Windows 大小写不敏感但 Linux 敏感,你传服务器或者用 U 盘拷贝后容易在文件名上翻车。

解决:先确认项目根目录下存在 templates 文件夹,和 app.py 同级;再逐个核对路由里的模板名和实际文件名,重点看大小写和斜杠方向;然后检查模板里引用的 CSS 路径,Flask 应该用url_for('static', filename='css/style.css')来生成静态资源地址,手写/static/css/style.css也勉强能用,但一旦项目挂到子路径下就会出问题。PyCharm 里如果你看到模板文件标红,右键 templates 文件夹选择 Mark Directory as Template Folder 就能恢复解析。

5.5 表单提交后 405 或 404

现象:登录页面输入账号密码点提交,地址栏变成 /login,然后页面提示405 Method Not Allowed,或者直接 404。

原因:405 是路由只写了 GET 没写 POST;404 多半是表单 action 手写路径和真实路由不一致,比如蓝图的 URL 前缀没写进去,/login写成/auth/login或者反过来。

解决:给路由方法的列表补上 POST:

@auth_bp.route("/login", methods=["GET", "POST"])

模板里的表单不要手写路径,用url_for:

<form action="{{ url_for('auth.login') }}" method="post">

这里的诀窍是:如果你不确定路由最终生成什么 URL,启动项目后在浏览器地址栏手动输入再回车,看它进不进得去;或者检查app.url_map,把所有已注册的路由和 methods 都列出来。删除功能如果出现 405,基本都是同一问题,检查 methods 即可。

6. 把项目升级成答辩亮点:统计图表、自动备份与自查清单

6.1 给首页加一个班级人数统计

学生管理系统只有表格和数据列表,看起来还是偏简陋。一个成本最低的升级方式是在首页加一个小型统计面板:查询每个班有多少学生,用柱状图展示。数据层只需要一条聚合 SQL:

SELECT c.class_name, COUNT(s.id) AS student_count FROM class c LEFT JOIN student s ON c.id = s.class_id GROUP BY c.id;

逻辑说明:这里用的是 LEFT JOIN,保证没有学生的班级也会出现在结果里,COUNT(s.id) 不会统计 NULL。后端写一个接口把它转成 JSON,前端用 Chart.js 画柱状图,前后加起来不到 50 行。你不需要搞复杂的可视化大屏,一个柱状图就足以让项目从“纯 CRUD”变成“有数据展示能力”。答辩的时候主动讲一句“这里我用的是 MySQL 的 GROUP BY 聚合查询,统计各班人数”,比被动等老师提问好得多。

6.2 数据库备份与恢复的兜底操作

答辩现场最怕的事就是演示时误删了一条学生记录,页面刷新后空了一行,你当时的表情会非常难看。所以演示前先做一次备份,这是后悔药:

# 备份 mysqldump -u root -p student_db > backup_$(date +%Y%m%d).sql # 恢复 mysql -u root -p student_db < backup_$(date +%Y%m%d).sql

逻辑说明:mysqldump 是 MySQL 自带的逻辑备份工具,导出的 sql 文件包含建表语句和 INSERT 数据。恢复命令会把当前库全部覆盖,所以执行前确认你不在生产环境。我自己的习惯是答辩前把备份文件复制一份到桌面和 U 盘,两处留存,演示前再跑一次启动流程确认页面正常,比在现场慌张找文件靠谱得多。

6.3 答辩前自查清单

按下面这张表逐项过一遍,每一项都是前面踩过坑的地方:

检查项怎么查常见问题
登录拦截未登录直接访问 /student/list 是否被重定向没做登录装饰器,页面被绕过
删除方式打开删除链接看 URL 是否为 POST 提交用了 GET 删除,误触无法挽回
字符集插入一条“张三”看显示是否正常乱码、问号
debug 模式检查 app.py 里 debug 是否为 False报错信息直接暴露给老师
端口占用重启前先查 5000 是否有残留进程Address already in use
数据库备份mysqldump 是否执行成功演示时数据丢失无法恢复

我第一次交课设时就是在删除功能上用了 GET,老师在台上点了一下带 id 的链接,数据当场就没了,场面非常尴尬。从那以后我每次做完功能都强制走一遍这份清单,特别是把删除改成 POST、关掉 debug、导出一次备份到桌面,再启动最后一遍确认流程能走通。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询