跳到主要内容Python Flask 实战:将本地学生成绩系统升级为在线 Web 应用 | 极客日志Python大前端算法
Python Flask 实战:将本地学生成绩系统升级为在线 Web 应用
基于 Flask 框架将本地 Python 脚本改造为在线 Web 应用。涵盖路由配置、模板继承、静态资源管理及数据可视化集成。实现首页展示、学生列表查询、图表报告生成及交互搜索功能。解决路径错误、请求方法匹配等常见问题,完成从数据处理到前端渲染的全流程开发。
PhpPioneer5 浏览 
之前的学生管理系统只能在自己电脑上运行,数据和图表都局限在本地文件里。今天咱们用 Python 的轻量级 Web 框架 Flask,把这套逻辑升级成在线 Web 应用。多人通过浏览器就能访问、查询成绩、查看可视化报告。
一、为什么选择 Flask?
本地脚本虽然方便,但无法共享数据,协作也不灵活。Web 应用只要有浏览器(电脑或手机)就能访问,数据集中存储,实时性更强。
Flask 的特点就是轻量、易上手,不需要复杂配置,特别适合快速把本地项目升级为 Web 服务。它还能无缝整合 Pandas、Matplotlib 等库,完美衔接咱们之前的数据处理代码。
简单说:Flask 能以最低的学习成本,让你的本地工具变成'人人可用的在线服务'。
二、Flask 基础:从 Hello World 到 Web 服务
先搞定安装和核心概念,跑通第一个 Web 服务建立认知。
1. 安装 Flask 与依赖
Flask 是第三方库,需要单独安装。同时我们还需要 Pandas(处理数据)、Matplotlib(生成图表):
pip install flask
pip install pandas matplotlib seaborn
安装完成后,打开终端输入 import flask,没报错就说明成功了。
2. 核心概念:Flask 的'三大件'
搞懂这三个概念就能入门 Web 开发:
- 路由(Route):URL 地址与 Python 函数的映射关系。比如访问
http://localhost:5000/ 对应执行 index() 函数。
- 视图函数(View Function):处理请求的逻辑函数,负责计算数据并返回响应(HTML 页面或字符串)。
- 模板(Template):用于渲染页面的 HTML 文件。通过 Jinja2 引擎,能把 Python 变量动态插入 HTML,让页面'活'起来。
3. 实战:跑通第一个 Flask 应用
创建一个名为 app.py 的主程序文件:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return "<h1>欢迎访问学生成绩管理系统!</h1><p>这是用 Flask 开发的 Web 应用</p>"
__name__ == :
app.run(debug=)
if
'__main__'
True
运行 python app.py,浏览器访问 http://localhost:5000/ 就能看到页面。
- 调试模式:
debug=True 很重要,开发时开启,改完代码不用手动重启。
- URL 映射:
@app.route('/') 对应根路径,如果定义 /student,访问该路径才会触发对应函数。
- 响应内容:目前返回的是简单 HTML 字符串,后面会用模板渲染更复杂的页面。
三、Flask 进阶:整合学生数据与 Web 页面
单纯的字符串不够美观,也无法展示表格。接下来用模板渲染 HTML,把 CSV 数据展示成 Web 表格。
1. 项目结构:规范文件组织
student_web/
├── app.py # 主程序
├── students_data.csv # 学生数据
├── templates/ # HTML 模板文件夹
│ ├── base.html # 基础模板
│ ├── index.html # 首页
│ └── student_list.html # 学生列表页
└── static/ # 静态资源(图片、CSS)
└── images/ # 图表文件夹
2. 模板继承:减少重复 HTML 代码
多个页面会有相同的导航栏和底部,用模板继承可以避免重复写。
创建基础模板 templates/base.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{% block title %}学生成绩管理系统{% endblock %}</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container">
<a class="navbar-brand" href="/">学生成绩系统</a>
<div class="collapse navbar-collapse">
<ul class="navbar-nav">
<li class="nav-item"><a class="nav-link" href="/">首页</a></li>
<li class="nav-item"><a class="nav-link" href="/student/list">学生列表</a></li>
<li class="nav-item"><a class="nav-link" href="/report">可视化报告</a></li>
</ul>
</div>
</div>
</nav>
<div class="container mt-4"> {% block content %}{% endblock %} </div>
<footer class="mt-5 py-3 bg-light text-center">
<div class="container"><p class="mb-0">© 2024 学生成绩管理系统 | 用 Flask 开发</p></div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
这里 {% block content %} 是子页面填充内容的地方,引入 Bootstrap 能让我们不写 CSS 也能做出美观的界面。
3. 首页开发:templates/index.html
{% extends "base.html" %}
{% block title %}首页 - 学生成绩管理系统{% endblock %}
{% block content %}
<div class="jumbotron bg-light p-5 rounded-3">
<h1 class="display-5 fw-bold">欢迎使用学生成绩管理系统</h1>
<p class="lead mt-3">本系统基于 Python Flask 开发,支持以下功能:</p>
<ul class="list-group list-group-flush mt-3 w-50">
<li class="list-group-item">查看所有学生的成绩列表</li>
<li class="list-group-item">查询单个学生的详细成绩</li>
<li class="list-group-item">查看各科成绩的可视化报告</li>
</ul>
<div class="mt-4">
<a href="/student/list" class="btn btn-primary me-3">进入学生列表</a>
<a href="/report" class="btn btn-success">查看可视化报告</a>
</div>
</div>
{% endblock %}
4. 学生列表页:展示 Pandas 处理的数据
在 app.py 中添加路由,读取 CSV 并传递给模板渲染。
修改 app.py
import pandas as pd
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/student/list')
def student_list():
df = pd.read_csv('students_data.csv', encoding='utf-8', dtype={'course_score': int})
df['grade'] = df['course_score'].apply(lambda x: 'A 级 (90+)' if x >= 90 else ('B 级 (80-89)' if x >= 80 else 'C 级 (<80)'))
student_data = df.to_dict('records')
total_students = df['name'].nunique()
total_courses = df['course_name'].nunique()
return render_template('student_list.html', students=student_data, total_students=total_students, total_courses=total_courses)
if __name__ == '__main__':
app.run(debug=True)
创建 templates/student_list.html
{% extends "base.html" %}
{% block title %}学生列表 - 学生成绩管理系统{% endblock %}
{% block content %}
<div class="d-flex justify-content-between align-items-center mb-4">
<h2>学生成绩列表</h2>
<p class="text-muted">总学生数:{{ total_students }} 人 | 总课程数:{{ total_courses }} 门</p>
</div>
<table class="table table-striped table-hover">
<thead class="table-dark">
<tr><th>学生姓名</th><th>年龄</th><th>课程名称</th><th>成绩(分)</th><th>成绩等级</th></tr>
</thead>
<tbody>
{% for student in students %}
<tr>
<td>{{ student.name }}</td>
<td>{{ student.age }}</td>
<td>{{ student.course_name }}</td>
<td>{{ student.course_score }}</td>
<td>
{% if student.grade == 'A 级 (90+)' %}
<span class="badge bg-success">{{ student.grade }}</span>
{% elif student.grade == 'B 级 (80-89)' %}
<span class="badge bg-warning">{{ student.grade }}</span>
{% else %}
<span class="badge bg-danger">{{ student.grade }}</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
访问 http://localhost:5000/student/list,就能看到带颜色标签的成绩表格。
四、Flask + 可视化:Web 页面展示图表
之前生成的图表存在本地,现在要让它们在网页上展示。
1. 修改 app.py,添加可视化报告路由
import matplotlib.pyplot as plt
import seaborn as sns
import os
plt.rcParams['font.sans-serif'] = ['SimHei', 'PingFang SC']
plt.rcParams['axes.unicode_minus'] = False
sns.set_style("whitegrid")
if not os.path.exists('static/images'):
os.makedirs('static/images')
@app.route('/report')
def report():
df = pd.read_csv('students_data.csv', encoding='utf-8', dtype={'course_score': int})
df['grade'] = df['course_score'].apply(lambda x: 'A 级 (90+)' if x >= 90 else ('B 级 (80-89)' if x >= 80 else 'C 级 (<80)'))
course_avg = df.groupby('course_name')['course_score'].mean().round(1)
fig, ax = plt.subplots(figsize=(6, 4), dpi=100)
bars = ax.bar(course_avg.index, course_avg.values, color='skyblue', edgecolor='black')
ax.set_title('各科平均分对比', fontsize=12)
ax.set_xlabel('课程名称')
ax.set_ylabel('平均分(分)')
ax.set_ylim(80, 90)
for bar in bars:
height = bar.get_height()
ax.text(bar.get_x() + bar.get_width() / 2, height + 0.5, str(height), ha='center', va='bottom')
plt.savefig('static/images/course_avg.png', bbox_inches='tight')
plt.close()
grade_count = df['grade'].value_counts()
fig, ax = plt.subplots(figsize=(6, 6), dpi=100)
colors = ['#FF6B6B', '#4ECDC4', '#45B7D1']
wedges, texts, autotexts = ax.pie(grade_count.values, labels=grade_count.index, autopct='%1.1f%%', startangle=90, colors=colors, explode=(0.05, 0, 0))
ax.set_title('成绩等级分布', fontsize=12)
for autotext in autotexts:
autotext.set_color('white')
plt.savefig('static/images/grade_pie.png', bbox_inches='tight')
plt.close()
return render_template('report.html')
2. 创建 templates/report.html
{% extends "base.html" %}
{% block title %}可视化报告 - 学生成绩管理系统{% endblock %}
{% block content %}
<h2>学生成绩可视化报告</h2>
<p class="text-muted mb-4">基于学生成绩数据生成的图表分析</p>
<div class="row g-4">
<div class="col-md-6">
<div class="card shadow-sm">
<div class="card-body">
<h5 class="card-title">各科平均分对比</h5>
<img src="{{ url_for('static', filename='images/course_avg.png') }}" alt="各科平均分柱状图" class="img-fluid">
</div>
</div>
</div>
<div class="col-md-6">
<div class="card shadow-sm">
<div class="card-body">
<h5 class="card-title">成绩等级分布</h5>
<img src="{{ url_for('static', filename='images/grade_pie.png') }}" alt="成绩等级饼图" class="img-fluid">
</div>
</div>
</div>
</div>
{% endblock %}
注意 url_for('static', ...) 是 Flask 辅助函数,自动生成静态文件 URL,比手动写路径更安全。
五、交互功能:学生成绩查询
只展示还不够,还要支持用户输入姓名查询。这需要用到表单处理。
1. 修改 app.py,添加查询路由
from flask import request
@app.route('/student/search', methods=['GET', 'POST'])
def student_search():
if request.method == 'GET':
return render_template('student_search.html')
elif request.method == 'POST':
student_name = request.form.get('student_name', '').strip()
if not student_name:
return render_template('student_search.html', error='请输入学生姓名!')
df = pd.read_csv('students_data.csv', encoding='utf-8', dtype={'course_score': int})
df['grade'] = df['course_score'].apply(lambda x: 'A 级 (90+)' if x >= 90 else ('B 级 (80-89)' if x >= 80 else 'C 级 (<80)'))
student_df = df[df['name'] == student_name]
if student_df.empty:
return render_template('student_search.html', error=f'未找到名为'{student_name}'的学生', input_name=student_name)
else:
student_data = student_df.to_dict('records')
total_score = student_df['course_score'].sum()
avg_score = student_df['course_score'].mean().round(1)
return render_template('student_search.html', student=student_data, total_score=total_score, avg_score=avg_score, input_name=student_name)
2. 创建 templates/student_search.html
{% extends "base.html" %}
{% block title %}学生查询 - 学生成绩管理系统{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-md-8">
<h2>学生成绩查询</h2>
<form method="POST" class="mt-4">
<div class="input-group mb-3">
<input type="text" name="student_name" class="form-control" placeholder="请输入学生姓名(如:小明)" value="{{ input_name if input_name else '' }}">
<button class="btn btn-primary" type="submit">查询</button>
</div>
{% if error %}
<div class="alert alert-danger" role="alert">{{ error }}</div>
{% endif %}
</form>
{% if student %}
<div class="card mt-4">
<div class="card-header bg-primary text-white">
<h5 class="mb-0"> {{ input_name }} 的成绩详情 <span class="float-end">总分:{{ total_score }} | 平均分:{{ avg_score }}</span></h5>
</div>
<div class="card-body">
<table class="table table-sm mb-0">
<thead><tr><th>课程名称</th><th>成绩(分)</th><th>成绩等级</th></tr></thead>
<tbody>
{% for item in student %}
<tr>
<td>{{ item.course_name }}</td>
<td>{{ item.course_score }}</td>
<td>
{% if item.grade == 'A 级 (90+)' %}<span class="badge bg-success">{{ item.grade }}</span>
{% elif item.grade == 'B 级 (80-89)' %}<span class="badge bg-warning">{{ item.grade }}</span>
{% else %}<span class="badge bg-danger">{{ item.grade }}</span>{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endif %}
</div>
</div>
{% endblock %}
这里 methods=['GET', 'POST'] 允许路由同时处理页面加载和表单提交。request.form.get 用来获取用户输入的值。
六、完整项目实战:在线学生成绩管理系统
现在系统有了首页、列表、报告、查询四个核心功能。最后回顾一下结构:
student_web/
├── app.py
├── students_data.csv
├── templates/
│ ├── base.html
│ ├── index.html
│ ├── student_list.html
│ ├── student_search.html
│ └── report.html
└── static/
└── images/
运行步骤很简单:确保文件结构正确,安装依赖,运行 python app.py,通过导航栏切换各个功能即可。
七、新手必踩的 5 个坑:避坑指南
- 模板路径错误:模板必须放在
templates 文件夹,文件名大小写要一致。
- 静态文件引用错误:不要用本地路径,要用
url_for('static', filename='...')。
- 请求方法错误:表单提交通常需要 POST,路由要显式指定
methods=['GET', 'POST']。
- 数据读取路径错误:CSV 文件最好放在项目根目录,或者使用
os.path.join 构建绝对路径。
- 调试模式关闭:开发时务必
debug=True,否则修改代码后不会自动重启。
注意:生产环境上线时要关闭 debug=True,防止安全风险。
八、小结与后续
这篇教程带你完成了从本地脚本到在线 Web 应用的跨越。掌握了 Flask 的路由、模板、静态资源管理以及数据可视化集成。下一步,我们会引入 SQLite 数据库替换 CSV 文件,实现数据的持久化存储和增删改查,让系统真正具备生产级别的能力。
相关免费在线工具
- 加密/解密文本
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
- Gemini 图片去水印
基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
- curl 转代码
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
- Markdown转HTML
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online