基于Flask的学生信息管理系统设计与实现

一、项目背景与意义

完整代码链接:https://pan.quark.cn/s/0221a7cc19f9

登录账号是admin/密码是admin123

1.1 项目背景

运行效果在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

随着高校招生规模的不断扩大,学生信息管理的工作量与日俱增。传统的手工管理方式或单机版管理软件已难以满足高效、准确、实时的管理需求。学生基本信息、课程安排、考试成绩等数据的分散管理,容易导致信息不一致、查询效率低下、统计分析困难等问题。

互联网技术的快速发展为教育信息化提供了有力的技术支撑。基于Web的学生信息管理系统能够实现数据的集中管理、实时更新和多点访问,极大地提高了管理效率。本系统采用Flask轻量级Web框架,结合SQLite数据库和Bootstrap前端框架,构建一套功能完善、操作简便的学生信息管理平台。

1.2 项目意义

  • 提升管理效率:将学生、班级、课程和成绩信息纳入统一管理平台,实现数据快速录入、查询和统计,减少人工操作错误率。
  • 数据可视化分析:通过ECharts图表直观展示成绩分布和统计数据,为教学管理决策提供数据支持。
  • 技术实践价值:综合运用Python Web开发、ORM数据库、前端响应式布局、数据可视化等技术,是Web全栈开发的完整实践。
  • 毕业设计参考:项目结构清晰、功能完整,可作为计算机相关专业毕业设计的参考案例。

二、系统需求分析

2.1 功能需求

本系统主要面向高校教务管理人员,核心功能模块包括:

(1)学生信息管理:学生基本信息的添加、修改、删除和查看;支持按学号/姓名模糊搜索和按班级筛选。

(2)班级信息管理:班级的添加、修改、删除;自动统计各班级学生人数;删除前检查是否存在关联学生。

(3)课程信息管理:课程的添加、修改、删除。

(4)成绩信息管理:成绩的录入、修改、删除;按学生和课程筛选查询;防止同一学生同一课程重复录入。

(5)成绩统计分析:各课程成绩统计(平均分、最高分、最低分、选课人数);各班级平均分对比;成绩等级分布;成绩排名前十学生展示。

(6)系统管理:管理员登录与身份验证;登录状态保持与会话管理。

2.2 非功能需求

  • 界面友好:Bootstrap响应式界面,适配不同屏幕尺寸
  • 操作简便:表单验证、操作提示、确认删除
  • 数据安全:密码加密存储、登录验证保护
  • 系统稳定:SQLite轻量数据库,部署简单

三、系统设计

3.1 系统架构设计

本系统采用B/S架构,整体为三层架构设计:

  • 表现层:Jinja2模板引擎渲染HTML,Bootstrap实现响应式布局,ECharts绘制图表
  • 业务逻辑层:Flask处理HTTP请求、路由分发、表单验证和业务逻辑
  • 数据访问层:SQLAlchemy ORM进行数据库操作

3.2 功能模块设计

  1. 登录认证模块:用户登录验证、会话管理、登录拦截
  2. 首页仪表盘模块:数据概览、快捷操作、成绩排名、成绩分布
  3. 学生管理模块:增删改查、搜索筛选、详情查看
  4. 班级管理模块:增删改查、学生人数统计
  5. 课程管理模块:增删改查
  6. 成绩管理模块:增删改查、筛选查询
  7. 成绩分析模块:课程统计分析、班级对比分析

3.3 数据库设计

系统使用SQLite数据库,共5张核心数据表。

用户表(users):id, username, password_hash, is_admin, created_at

班级表(classes):id, name, department, grade_year, created_at

学生表(students):id, student_no(唯一索引), name, gender, birth_date, phone, email, address, enrollment_date, class_id(外键), created_at

课程表(courses):id, name, code(唯一索引), credit, teacher, semester, created_at

成绩表(grades):id, student_id(外键), course_id(外键), score, semester, created_at

3.4 实体关系

  • 一个班级包含多名学生(一对多)
  • 一名学生可选修多门课程,一门课程可被多名学生选修(多对多,通过成绩表关联)

四、系统实现

4.1 项目结构

基于Flask的学生信息管理系统设计与实现/
├── app.py                # 主应用(路由+启动)
├── config.py             # 配置
├── models.py             # 数据模型
├── forms.py              # 表单定义
├── requirements.txt      # 依赖
├── static/css/style.css  # 样式
├── static/js/main.js     # 脚本
└── templates/            # 模板
    ├── base.html         # 基础模板
    ├── login.html        # 登录
    ├── dashboard.html    # 首页
    ├── students/         # 学生管理
    ├── classes/          # 班级管理
    ├── courses/          # 课程管理
    └── grades/           # 成绩管理+分析

4.2 技术选型

技术 版本 用途
Python 3.8+ 开发语言
Flask 2.3.3 Web框架
Flask-SQLAlchemy 3.1.1 ORM
Flask-Login 0.6.3 登录管理
Flask-WTF 1.2.1 表单+CSRF
Werkzeug 2.3.7 密码加密
Bootstrap 5.3.2 UI框架
ECharts 5.4.3 可视化

4.3 核心代码实现

4.3.1 应用配置(config.py)
import os
basedir = os.path.abspath(os.path.dirname(__file__))

class Config:
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'studentms-secret-key-2024'
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
        'sqlite:///' + os.path.join(basedir, 'studentms.db')
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    WTF_CSRF_ENABLED = True

SECRET_KEY用于会话加密和CSRF令牌生成;SQLALCHEMY_DATABASE_URI指定SQLite数据库文件路径;WTF_CSRF_ENABLED开启跨站请求伪造防护。

4.3.2 数据模型(models.py)
from flask_sqlalchemy import SQLAlchemy
from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash
from datetime import datetime

db = SQLAlchemy()


class User(UserMixin, db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, nullable=False, index=True)
    password_hash = db.Column(db.String(256), nullable=False)
    is_admin = db.Column(db.Boolean, default=True)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)


class Class(db.Model):
    __tablename__ = 'classes'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    department = db.Column(db.String(100))
    grade_year = db.Column(db.String(20))
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    students = db.relationship('Student', backref='class_', lazy='dynamic')

    def student_count(self):
        return self.students.count()


class Student(db.Model):
    __tablename__ = 'students'
    id = db.Column(db.Integer, primary_key=True)
    student_no = db.Column(db.String(20), unique=True, nullable=False, index=True)
    name = db.Column(db.String(50), nullable=False)
    gender = db.Column(db.String(10))
    birth_date = db.Column(db.Date)
    phone = db.Column(db.String(20))
    email = db.Column(db.String(100))
    address = db.Column(db.String(200))
    enrollment_date = db.Column(db.Date)
    class_id = db.Column(db.Integer, db.ForeignKey('classes.id'))
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    grades = db.relationship('Grade', backref='student', lazy='dynamic')


class Course(db.Model):
    __tablename__ = 'courses'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    code = db.Column(db.String(20), unique=True, nullable=False)
    credit = db.Column(db.Float, default=1.0)
    teacher = db.Column(db.String(50))
    semester = db.Column(db.String(20))
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    grades = db.relationship('Grade', backref='course', lazy='dynamic')


class Grade(db.Model):
    __tablename__ = 'grades'
    id = db.Column(db.Integer, primary_key=True)
    student_id = db.Column(db.Integer, db.ForeignKey('students.id'), nullable=False)
    course_id = db.Column(db.Integer, db.ForeignKey('courses.id'), nullable=False)
    score = db.Column(db.Float)
    semester = db.Column(db.String(20))
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

每个模型类对应一张数据库表。db.Column定义字段属性(类型、是否为空、是否唯一等),db.relationship定义对象关系映射,ForeignKey建立外键关联。用户模型使用werkzeug.security进行密码加密存储,确保数据安全。

4.3.3 表单定义(forms.py)
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SelectField, FloatField, DateField, SubmitField
from wtforms.validators import DataRequired, Length, Optional, NumberRange


class StudentForm(FlaskForm):
    student_no = StringField('学号', validators=[DataRequired(), Length(1, 20)])
    name = StringField('姓名', validators=[DataRequired(), Length(1, 50)])
    gender = SelectField('性别', choices=[('男', '男'), ('女', '女')])
    birth_date = DateField('出生日期', format='%Y-%m-%d', validators=[Optional()])
    phone = StringField('联系电话', validators=[Optional(), Length(0, 20)])
    email = StringField('电子邮箱', validators=[Optional(), Length(0, 100)])
    address = StringField('家庭地址', validators=[Optional(), Length(0, 200)])
    enrollment_date = DateField('入学日期', format='%Y-%m-%d', validators=[Optional()])
    class_id = SelectField('所属班级', coerce=int, validators=[Optional()])
    submit = SubmitField('保存')


class LoginForm(FlaskForm):
    username = StringField('用户名', validators=[DataRequired(), Length(1, 64)])
    password = PasswordField('密码', validators=[DataRequired()])
    submit = SubmitField('登录')


class ClassForm(FlaskForm):
    name = StringField('班级名称', validators=[DataRequired(), Length(1, 100)])
    department = StringField('所属院系', validators=[Optional(), Length(0, 100)])
    grade_year = StringField('年级', validators=[Optional(), Length(0, 20)])
    submit = SubmitField('保存')


class CourseForm(FlaskForm):
    name = StringField('课程名称', validators=[DataRequired(), Length(1, 100)])
    code = StringField('课程编号', validators=[DataRequired(), Length(1, 20)])
    credit = FloatField('学分', validators=[Optional(), NumberRange(0, 20)])
    teacher = StringField('授课教师', validators=[Optional(), Length(0, 50)])
    semester = StringField('开课学期', validators=[Optional(), Length(0, 20)])
    submit = SubmitField('保存')


class GradeForm(FlaskForm):
    student_id = SelectField('学生', coerce=int, validators=[DataRequired()])
    course_id = SelectField('课程', coerce=int, validators=[DataRequired()])
    score = FloatField('成绩', validators=[Optional(), NumberRange(0, 100)])
    semester = StringField('学期', validators=[Optional(), Length(0, 20)])
    submit = SubmitField('保存')

WTForms自动生成HTML表单控件并执行数据验证。DataRequired为必填,Optional为可选,NumberRange限制数值范围,SelectFieldcoerce=int将选项值转为整数。

4.4 主应用与路由(app.py)

4.4.1 应用工厂
def create_app():
    app = Flask(__name__)
    app.config.from_object(Config)

    db.init_app(app)
    login_manager.init_app(app)

    with app.app_context():
        db.create_all()
        if not User.query.filter_by(username='admin').first():
            admin = User(username='admin')
            admin.set_password('admin123')
            db.session.add(admin)
            db.session.commit()

    register_routes(app)
    return app

应用启动时自动建表并初始化默认管理员(admin / admin123),省去手动配置数据库的步骤。

4.4.2 学生列表(分页+搜索+筛选)
@app.route('/students')
@login_required
def student_list():
    page = request.args.get('page', 1, type=int)
    keyword = request.args.get('keyword', '', type=str)
    class_id = request.args.get('class_id', 0, type=int)

    query = Student.query
    if keyword:
        query = query.filter(
            Student.name.contains(keyword) |
            Student.student_no.contains(keyword)
        )
    if class_id:
        query = query.filter(Student.class_id == class_id)

    pagination = query.order_by(Student.id.desc()).paginate(
        page=page, per_page=10, error_out=False
    )
    students = pagination.items
    classes = Class.query.all()
    return render_template('students/list.html',
                           students=students, pagination=pagination,
                           classes=classes, keyword=keyword,
                           selected_class_id=class_id)

使用Flask的paginate实现分页,通过contains实现模糊搜索,路由参数实现班级筛选。

4.4.3 成绩分析(聚合查询)
@app.route('/grades/analysis')
@login_required
def grade_analysis():
    course_stats = db.session.query(
        Course.id, Course.name,
        func.count(Grade.id).label('student_count'),
        func.avg(Grade.score).label('avg_score'),
        func.max(Grade.score).label('max_score'),
        func.min(Grade.score).label('min_score')
    ).join(Grade, Course.id == Grade.course_id
    ).group_by(Course.id).all()

    class_stats = db.session.query(
        Class.name,
        func.avg(Grade.score).label('avg_score'),
        func.count(Grade.id).label('grade_count')
    ).join(Student, Grade.student_id == Student.id
    ).join(Class, Student.class_id == Class.id
    ).group_by(Class.id).all()

    return render_template('grades/analysis.html',
                           course_stats=course_stats,
                           class_stats=class_stats)

使用SQLAlchemy的func.avgfunc.countfunc.maxfunc.min聚合函数,通过join多表连接和group_by分组,实现复杂的统计分析。

4.4.4 登录验证
@app.route('/login', methods=['GET', 'POST'])
def login():
    if current_user.is_authenticated:
        return redirect(url_for('dashboard'))
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data).first()
        if user and user.check_password(form.password.data):
            login_user(user)
            flash('登录成功', 'success')
            return redirect(url_for('dashboard'))
        flash('用户名或密码错误', 'danger')
    return render_template('login.html', form=form)

登录流程:用户提交凭据 → 数据库查询 → 密码哈希校验 → Flask-Login建立会话 → 重定向首页。

4.4.5 成绩防重复录入
existing = Grade.query.filter_by(
    student_id=form.student_id.data,
    course_id=form.course_id.data
).first()
if existing:
    flash('该学生已存在此课程的成绩记录', 'warning')
    return render_template('grades/add.html', form=form)

录入成绩前查询是否已存在相同学生+课程的记录,避免数据冗余。

4.5 前端实现

4.5.1 基础模板(base.html)

基础模板定义整体布局,所有页面通过Jinja2模板继承机制复用导航栏、消息提示和公共脚本。

{% if current_user.is_authenticated %}
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
    ...
</nav>
{% endif %}
4.5.2 ECharts数据可视化

首页仪表盘的成绩分布环形图:

var chart = echarts.init(document.getElementById('gradeChart'));
var option = {
    tooltip: { trigger: 'item', formatter: '{b}: {c} 人 ({d}%)' },
    legend: { bottom: '0%' },
    series: [{
        type: 'pie',
        radius: ['40%', '70%'],
        label: { show: true, formatter: '{b}: {c}' },
        data: [
            { value: 15, name: '优秀' },
            { value: 30, name: '良好' },
            ...
        ]
    }]
};
chart.setOption(option);

radius: ['40%', '70%']实现环形图效果,{b}{c}为模板变量,分别代表名称和数值。

五、系统功能展示

5.1 登录页面

渐变背景居中布局,包含系统名称、用户名/密码输入框和登录按钮。默认凭据:admin / admin123。

5.2 首页仪表盘

  • 顶部四个统计卡片(学生总数、课程总数、班级总数、成绩记录数)
  • 左侧成绩等级分布环形图
  • 右侧平均分排名前十学生列表
  • 底部快捷操作按钮

5.3 学生管理

  • 列表支持搜索(学号/姓名)和班级筛选,分页每页10条
  • 查看详情:左侧基本信息 + 右侧成绩记录(颜色区分等级)
  • 添加/编辑:统一表单,学号姓名为必填,班级下拉选择

5.4 班级管理

班级列表含学生人数统计。删除时检查关联学生,确保数据完整性。

5.5 课程管理

课程列表含课程编号、学分、授课教师等信息。

5.6 成绩管理

  • 按学生和课程两个维度筛选
  • 成绩以颜色徽标区分等级
  • 自动防止重复录入

5.7 成绩分析

  • 各课程平均分柱状图
  • 各班级平均分柱状图
  • 课程详细统计表(选课人数、平均分、最高分、最低分)

六、系统部署

6.1 环境准备

Python 3.8+,建议使用虚拟环境。

6.2 安装依赖

pip install -r requirements.txt

6.3 启动系统

python app.py

访问 http://127.0.0.1:5000。首次启动自动创建SQLite数据库并初始化管理员。

七、总结与展望

7.1 项目总结

  1. 功能完整:学生、班级、课程、成绩四大模块增删改查 + 统计分析
  2. 技术综合:Python Web + ORM + 响应式布局 + 数据可视化
  3. 体验良好:界面简洁、流程清晰、提示完善
  4. 安全可靠:密码加密、登录拦截、CSRF防护
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐