一. 项目功能概述

本次项目使用Python语言编写的Flask框架下的web应用。主要用到的技术有MySQL、HTML前端以及Flask框架。该项目的主要功能有实现管理员的登录、学生信息的图表统计、学生信息的增删改查、学生成绩的增删改查、学生选课情况的修改与查询、学生奖惩情况的图表统计以及修改和删除、对已毕业学生的毕业去向进行图表统计。以上功能共有14个前端页面,后端封装成三个模块文件,同时在MySQL中共建有5张表格。

二.项目实现步骤

1.项目的搭建

本次项目的编码环境为Pycharm2021专业版,首先我们创建名为student_system的python项目,由于我们采用的是Flask框架,所以我们需要在Flask框架下新建static文件夹用来存储静态文件,新建templates文件夹用于存储HTML模板文件,具体结构如下图1所示。app.py文件是接口模块,用来连接前端页面。获取前端页面的数据或者将前端数据传送到后端,同时里面还定义了很多的动态路由以及与路由相关的视图函数。studentdata.py模块里定义了与数据库中表格相关联的类,类中定义了很多的方法用来对数据库进行增删改查。Functions.py模块主要用于定义创建studentdata.py模块的实例化对象并调用相应的方法。

499cf4559097456580527fcb2bf0b128.png

 

图1 项目结构

接着我们来创建名为student的数据库,在库中创建5张表。students表为学生信息表,course表为学生选课表,direction表为已毕业学生的毕业去向表,grades表为学生的成绩表,rewards表为学生的奖惩情况表,各表中字段如图2所示。

52c9f8035a1a4d80945826a760f03ec6.png

 图2 数据库表中各字段

2.登录功能及主页面的展示

 

在登录功能中,由于涉及到对数据进行增删改查,为了该管理系统的安全性,我们只允许学校的管理人员进行登录,非管理人员则无权登录。因此我们给定管理员用户名为“admin”,密码为“123456”。我们输入用户名和密码点击登录后,会跳转至主页面。同时在app.py模块中定义登录接口以及主页面接口,用以跳转页面。

functions.py

 

# 登录功能def login():    username = request.form.get('username')    password = request.form.get('password')    if username != 'admin':        return '账号错误,请重新输入!'    else:        if password == '123456':            session['username'] = username            return 1        else:            return "密码错误,请重新登录"

app.py

9b4ff8a4066d455c9f37b840ddfb0553.png

 登录界面

c0a0014d7e6d4aa2990f7016efed0b92.png

 主界面

3.图表展示功能

在图表展示功能以及毕业去向和奖惩情况页面,我们需要将从数据库获取到的数据进行图表展示的形式,直观的展现到前端页面。我们需要用到python中的第三方库pyecharts,我们打开cmd运行框输入pip install pyecharts进行下载。如我们需要展示各二级学院的人数,我们在studentdata.py模块中创建Student类,并初始化属性,定义查询二级学院的方法,并将结果以列表的形式返回。在functions.py模块中我们导入studentdata模块,定义各二级学院名字的列表depart_lst,遍历depart_lst进行批量创建实例化对象并调用查找二级学院的方法,将返回的列表的长度即为每个二级学院的人数存储到num_lst中。通过Bar函数来创建图表,x轴为depart-lst,y轴为num_lst,设置标题为“各学院学生人数”。最终调用dump_options()这个方法将图表绘制在网页中。不过该需要自己引入echarts.js文件,该js文件可以在相对应的网站进行打包下载。接着我们在app.py模块添加与前端页面相对应的路由,并配置视图函数,在视图函数中调用该方法,将图表传至前端页面,同时在前端页面中我们通过echarts函数将其展示到前端页面中。

charts.html界面

5d169118e8a447a49626e550d77630c0.png

 

studentdata.py

 # 查询各个学院的学生姓名    def search_department(self):        # ping()使用该方法 ping(reconnect=True) ,那么可以在每次连接之前,会检查当前连接是否已关闭,如果连接关闭则会重新进行连接。        db.ping(reconnect=True)        # 插入sql语句        sql = "SELECT name FROM students WHERE department='" + self.department + "'"        # 执行sql语句        cursor.execute(sql)        results1 = cursor.fetchall()        results = []        for item in results1:            results.append(item)        # 关闭数据库        db.close()        # 返回结果        return results

functions.py

# 图表展示各二级学院人数def char_department():    depart_lst = ['理学院', '计算机学院', '电子学院', '商学院', '海外教育学院', '地理学院']    num_lst = []    for item in depart_lst:        student = std.Student('', '', '', '', '', f'{item}', '')        num_lst.append(len(student.search_department()))    bar = (Bar(init_opts=opts.InitOpts(bg_color='lightskyblue')).add_xaxis(depart_lst)           .add_yaxis("人数", num_lst).set_global_opts(title_opts=opts.TitleOpts(title="各学院学生人数")))    bar_options = bar.dump_options()    return bar_options

app.py

# 图表统计页面接口@app.route('/charts')def charts():    bar_options = func.char_department()    pie_options = func.char_gender()    bar_options1 = func.char_age()    return render_template('charts.html', bar_options=bar_options, pie_options=pie_options, bar_options1=bar_options1)

charts.html

     <div id="main1" style="width:100%;height: 300px"></div>            <div id="main2" style="width:100%;height: 200px"></div>            <div id="main3" style="width:100%;height: 300px"></div>            <script type="text/javascript">                var  mychart1=echarts.init(document.getElementById('main1'),'walden');                var mychart2=echarts.init(document.getElementById('main2'));                var mychart3=echarts.init(document.getElementById('main3'));                mychart1.setOption({{ bar_options|safe }});                mychart2.setOption({{ pie_options|safe }});                mychart3.setOption({{ bar_options1|safe }});            </script>

4.增删改查功能

该功能主要用于在学生成绩页面、学生信息页面、奖惩情况页面以及学生选课页面。如学生成绩页面有查询成绩、录入成绩、修改成绩以及删除成绩的功能。由于每个页面的功能都类似,我们仅以学生成绩界面加以说明。首先我们对成绩进行查询,在studentdata定义Grade类,定义输入学号查询成绩的方法,并以列表的形式返回,在functions模块中定义查询成绩的函数,并给定形参snum为学号,创建实例化对象并调用方法,将结果以列表的形式返回。在app.py模块中定义查询成绩的路由以及视图函数。在视图函数中去调用functions模块中的查询成绩的函数,并将前端输入框的学号作为实参,将列表传至前端页面。在前端页面中我们通过jinja2模板来对列表进行遍历,以表格的形式展示到前端页面中。

接着我们对成绩进行修改和删除,具体流程与上述查询成绩类似。我们先在studentdata.py模块中Grade类里定义修改和删除的方法,对数据操作时,修改会用到UPDATE语句而删除用到的是DELETE语句。在functions类中定义修改的函数,并添加形参snum,创建实例化对象,并将学号传入对象中,并调用方法。由于在app.py接口中还需要获取前端页面获取的值,为了接口模块的简洁,我们将获取前端的值一并写入functions中。最后在app模块中直接调用并传入实参即可。在删除学生成绩中,代码量比较少,我们直接在app.py模块接口中创建Grade的实例化,并传入实参调用删除学生成绩的方法即可。

最后我们对录入成绩进行实现,我们需要用到INSERT语句来将数据添加到数据库中。首先在前端页面中,我们以表格的形式将输入框展示到页面中。在studentdata.py模块中,我们在Grade类中定义录入成绩的方法,通过INSERT SQL语句将数据加入到数据库成绩表中。在这里我们需要注意的是pymysql在进行插入数据时,如果是varchar或string类型,需要使用Python中的repr()函数将对象转化为供解释器读取的形式。在function.py模块中我们定义录入成绩的函数,获取前端页面输入的值,创建实例化方法传入参数并调用方法。在HTTP中,常见的请求方法有GET和POST。GET请求中的参数包含在URL里面,数据可以在URL中看到,而POST的请求的URL不会包含这些数据;同时GET请求提交的数据最多只有1024字节,而POST方式没有限制。在app.py模块中我们定义录入成绩的视图函数,同时为了防止数据的泄露,我们在视图函数中判断请求的方法是GET请求还是POST请求,如果是GET请求,我们则展示页面,如果是POST请求,我们则调用录入成绩的函数,并将页面重定向至查询成绩界面。其他界面的增删改查与上述基本一致。

查询全部成绩

195fbad86724429b80cc9fea2c1ae22d.png

 单个查询

5463b62fe83a493996a4520ae28d54ee.png

 录入成绩

f91d48aa0c2a4982b7a1fd54bf89a80c.png

 e83209a620c147dd97ae17d295a2e67e.png

 删除成绩

b0a2838e4905441d8f9285236dbf5239.png

 

studentdata.py

class Grade:    def __init__(self, snum, course1, course2, course3, course4):        self.snum = snum        self.course1 = course1        self.course2 = course2        self.course3 = course3        self.course4 = course4    # 按学号查询学生的成绩    def search_snum_grade(self):        # ping()使用该方法 ping(reconnect=True) ,那么可以在每次连接之前,会检查当前连接是否已关闭,如果连接关闭则会重新进行连接。        db.ping(reconnect=True)        # 插入sql语句        sql = "SELECT *  FROM grades WHERE snum='" + self.snum + "'"        # 执行sql语句        cursor.execute(sql)        results1 = cursor.fetchone()        results = []        for item in results1:            results.append(item)        # 关闭数据库        db.close()        # 返回结果        return results    # 查询学生的成绩    def search_grade(self):        db.ping(reconnect=True)        # 插入sql语句        sql = "SELECT * FROM grades"        # 执行sql语句        cursor.execute(sql)        results1 = cursor.fetchall()        results = []        for item in results1:            results.append(list(item))        # 关闭数据库        db.close()        # 返回结果        return results    # 修改学生成绩    def update_grade(self):        # ping()使用该方法 ping(reconnect=True) ,那么可以在每次连接之前,会检查当前连接是否已关闭,如果连接关闭则会重新进行连接。        db.ping(reconnect=True)        # 插入sql语句        sql = "UPDATE grades SET course1='" + self.course1 + "',course2='" + self.course2 + "',course3='" + self.course3 + "', course4='" + self.course4 + "' WHERE snum='" + self.snum + "'"        # 执行sql语句        cursor.execute(sql)        db.commit()        db.close()    # 删除学生成绩    def delete_grade(self):        # ping()使用该方法 ping(reconnect=True)        db.ping(reconnect=True)        sql = "DELETE FROM grades WHERE snum='" + self.snum + "' "        cursor.execute(sql)        # 提交到数据库执行        db.commit()        # 关闭数据库        db.close()    # 录入成绩    def add_grade(self):        # ping()使用该方法 ping(reconnect=True)        db.ping(reconnect=True)        # 编写sql语句        sql_0 = "INSERT INTO grades(snum,course1,course2,course3,course4) VALUES(%s,%s,%s,%s,%s)"        sql = sql_0 % (repr(self.snum), repr(self.course1),                       repr(self.course2), repr(self.course3), repr(self.course4))        cursor.execute(sql)        # 提交到数据库执行        db.commit()        # 关闭数据库        db.close()


functions.py

# 按学号查找单个学生的成绩def search_snum_grade(snum):    grade_lst = []    grade_lst.append(std.Grade(snum, '', '', '', '').search_snum_grade())    return grade_lst# 查找全部学生的成绩def search_grade():    grade_lst = (std.Grade('', '', '', '', '').search_grade())    return grade_lst# 修改学生成绩def update_grade(snum):    st = []    lst = ['course1', 'course2', 'course3', 'course4']    for item in lst:        st.append(request.form.get(f'{item}'))    std.Grade(snum, st[0], st[1], st[2], st[3]).update_grade()# 录入学生成绩def add_grade():    lst = ['snum', 'course1', 'course2', 'course3', 'course4']    grade_lst = []    for item in lst:        grade_lst.append(request.form.get(f'{item}'))    std.Grade(grade_lst[0], grade_lst[1], grade_lst[2], grade_lst[3], grade_lst[4]).add_grade()

app.py

# 学生成绩界面接口(按学号查)@app.route('/grade', methods=['GET', 'POST'])def grade():    if request.method == 'GET':        return render_template('grade.html')    if request.method == 'POST':        grade_lst = func.search_snum_grade(request.form.get('snum'))        return render_template('grade.html', grade_lst=grade_lst)# 全部学生成绩界面接口@app.route('/all-grade')def all_grade():    grade_lst1 = func.search_grade()    return render_template('grade.html', grade_lst1=grade_lst1)# 修改学生成绩@app.route('/update-grade/<grade_list>', methods=['GET', 'POST'])def update_grade(grade_list):    snum = grade_list[2:6]    grade_list1 = func.search_snum_grade(snum)    if request.method == 'GET':        return render_template('update-grade.html', grade_list1=grade_list1, snum=snum)    if request.method == 'POST':        func.update_grade(snum)        return redirect('/grade')# 删除学生成绩的接口@app.route('/delete-grade/<grade_list>')def delete_grade(grade_list):    num = grade_list[2:6]    std.Grade(num, '', '', '', '').delete_grade()    return redirect('/grade')# 录入学生成绩的接口@app.route('/add-grade', methods=['GET', 'POST'])def add_grade():    if request.method == 'GET':        return render_template('add-grade.html')    if request.method == 'POST':        func.add_grade()        return redirect('/grade')

grade.html

<div id="content">    <div id="content-header">        <div id="breadcrumb"><a href="#" title="Go to Home" class="tip-bottom"><i class="icon-home"></i> Home</a> <a                href="#" class="current">学生成绩录入及查询</a></div>    </div>           <div id="data3" style="width: 100%">            <form action="" method="post">                <label>                    <input style="height: 30px" type="text" name="snum" placeholder="输入学号查询成绩"/>                    <input type="submit" style="height: 30px" value="查询" href="/grade">                    <a href="/all-grade" style="margin-left: 20px;color: #0e90d2">查询全部</a>                    <a href="/grade" style="margin-left: 30px;color: #0e90d2">返回单个查询</a>                    <a href="/add-grade" style="margin-left: 30px;color: #0e90d2">录入学生成绩</a>                </label>            </form>            {% if grade_lst|length==1 %}                <table style="width: 80%;margin-left: 88px;background:coral;">                    <caption>学生成绩&#12288;共{{ grade_lst|length }}条记录</caption>                    <tr>                        <td style="width: 87px;text-align: center">学号</td>                        <td style="width: 87px;text-align: center">课程一</td>                        <td style="width: 87px;text-align: center">课程二</td>                        <td style="width: 87px;text-align: center">课程三</td>                        <td style="width: 87px;text-align: center">课程四</td>                        <td style="width: 87px;text-align: center">修改操作</td>                        <td style="width: 87px;text-align: center">删除操作</td>                    </tr>                    {% for item in grade_lst %}                        <tr>                            {% for items in item %}                                <td style="width: 87px;text-align: center">{{ items }}</td>                            {% endfor %}                            <td style="width: 87px;text-align: center"><a href="/update-grade/{{ item }}">修改</a>                            </td>                            <td style="width: 87px;text-align: center"><a href="/delete-grade/{{ item }}"                                                                          onclick="delete_grade()">删除</a>                            </td>                        </tr>                    {% endfor %}                </table>            {% else %}                <table style="width: 80%;margin-left: 88px;background: #5bc0de">                    <caption>学生成绩&#12288;共{{ grade_lst1|length }}条记录</caption>                    <tr>                        <td style="width: 87px;text-align: center">学号</td>                        <td style="width: 87px;text-align: center">课程一</td>                        <td style="width: 87px;text-align: center">课程二</td>                        <td style="width: 87px;text-align: center">课程三</td>                        <td style="width: 87px;text-align: center">课程四</td>                        <td style="width: 87px;text-align: center">修改操作</td>                        <td style="width: 87px;text-align: center">删除操作</td>                    </tr>                    {% for item in grade_lst1 %}                        <tr>                            {% for items in item %}                                <td style="width: 87px;text-align: center">{{ items }}</td>                            {% endfor %}                            <td style="width: 87px;text-align: center"><a href="/update-grade/{{ item }}">修改</a>                            </td>                            <td style="width: 87px;text-align: center"><a href="/delete-grade/{{ item }}"                                                                          onclick="delete_grade()">删除</a>                            </td>                        </tr>                    {% endfor %}                </table>            {% endif %}        </div>

github源码地址:   ​​​​​​https://github.com/JBZ0805/student_system.git

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐