基于python,mysql的学生打卡系统(班级在用)
本文约有1.8W字,快来数一数 读一读吧
本文目录
- 前言
- 一、建立基础数据库(数据库名:english punch)
- all_name表:用于存储所有学生信息
- update_table表:用于记录打卡信息
- visit表:存储访问信息
- 二、 用处不大的表
- pharse表:存储成语信息
- 三、写前端
- 1. 主页面
- 2. 统计页面
- 3. 关于页面
- 4. 彩蛋(直接copy的)
- 5. 猜成语
- 四、写后端
- 1. app.py
- 2. sql_fun内部
- 3. helplist.txt
- 五、辅助文件
- 1. run.bat
- 2. 项目目录
- 六、留个地方放项目网址
- 等项目测试打包好会上传到GitHub或其他网站,链接会放这里。
- 写在最后:生活不易,高中生也叹气。
前言
本项目由某不知名学校的高中生开发。
本项目为一个基于python,flask,pymysql的学生打卡系统,开发环境PyCharm 2021.3.2,运行环境Windows server 2022。
- 开发背景
受疫情影响,我们学校进入了网课阶段,往常的打卡手段为微信群的接龙,但是由于消息过多,容易将上课等重要信息覆盖,所以出现了这个项目。 - 系统优缺点
优点:直观看到学生打卡情况
缺点:同学不喜欢 界面丑陋(很少的css,时间紧没写界面) - 自认为nb之处
记忆名字:通过记录每次打卡的IP进行查询。
将画图步骤转化到打卡过程(详情请转到:四、1)
直接看图:
一、建立基础数据库(数据库名:english punch)
all_name表:用于存储所有学生信息
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for all_name
-- ----------------------------
DROP TABLE IF EXISTS `all_name`;
CREATE TABLE `all_name` (`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,`class` int(0) NULL DEFAULT NULL,PRIMARY KEY (`name`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;
- name:学生姓名
- class:学生班级
如图:
update_table表:用于记录打卡信息
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for update_table
-- ----------------------------
DROP TABLE IF EXISTS `update_table`;
CREATE TABLE `update_table` (`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,`class` int(0) NULL DEFAULT NULL,`date` datetime(0) NOT NULL,`ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,`vid` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;
- name:打卡姓名
- class:学生班级
- date:打卡时间
- IP:当前打卡的IP,目的:记忆用户名
- vid:浏览器唯一标识,目的:为防止重复打卡 (停用了)
如图:
visit表:存储访问信息
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for visit
-- ----------------------------
DROP TABLE IF EXISTS `visit`;
CREATE TABLE `visit` (`time` datetime(0) NULL DEFAULT NULL,`ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,`thing` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;
- time:访问时间
- IP:访问的IP
- thing:本次事件
如图
二、 用处不大的表
或者说是无用表
pharse表:存储成语信息
(本来是英语打卡来着)
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for phrase
-- ----------------------------
DROP TABLE IF EXISTS `phrase`;
CREATE TABLE `phrase` (`question` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,`answer` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,`source` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,`study` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,`abbr` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,`quanpin` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;
- question:存储问题(成语意思)
- answer:存储答案
- source:存储出处
- study:存储例句
- abbr:存储首拼
- quanpin:存储全拼
如图:
三、写前端
1. 主页面
主页面采用简洁风 (没空写css)
文件:main.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>英语听力接龙{{ date }}</title><meta name="viewport"content="width=device-width, initial-scale=1.0, minimum-scale=0.5, maximum-scale=2.0, user-scalable=yes" /><!--引入jQuery包用于使用ajax--><script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script><h4>今天是:{{ date }} 欢迎进行听力接龙</h4><h4>请输入你的名字 是实名制的哦</h4>你的名字<input type="text" id="name" name="name" placeholder="姓名" value="{{ name }}"><h1></h1><button onclick="add_fun();" id="send_mess">提交打卡</button><button onclick="search_fun();">统计数据</button><button onclick="help_fun()">关于</button><button onclick="heart()">小彩蛋</button><button onclick="p()">猜猜成语</button><h3>彩蛋中的姓名是文本框内容 可以自行编辑</h3><script>function heart(){$.ajax({url : "heart",type : "POST",data: { "name": $("#name").val()},success: function (result) {document.write(result)}});}function help_fun() {$.ajax({url : "about",type : "POST",success: function (result) {document.write(result)}});}function search_fun() {$.ajax({url:"s",type:"POST",success:function (res){document.write(res);}})}visitorId = "";function get_vid(){const fpPromise = import('https://openfpcdn.io/fingerprintjs/v3').then(FingerprintJS => FingerprintJS.load())// Get the visitor identifier when you need it.fpPromise.then(fp => fp.get()).then(result => {// This is the visitor identifier:visitorId = result.visitorId;});}window.οnlοad=get_vid();function add_fun() {if($("#name").val().length===0){alert("名字不能留空");return;}$("#send_mess").attr('disabled',true);$.ajax({url: "add",type: "POST",data: { "name": $("#name").val(), "vid":visitorId},success: function (result) {if (result.message == "OK") {alert("提交成功");document.getElementById("name").value = "";}else if(result.message == "E"){alert("其他错误 请联系周景鑫");}else{alert(result.message);}$("#send_mess").attr('disabled',false);}});}function p(){$.ajax({url: "p",type: "POST",success: function (res) {document.write(res);}});}</script>
</head>
<body></body>
</html>
如图:
2. 统计页面
文件:statistics.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=0.5, maximum-scale=2.0, user-scalable=yes" /><title>{{ date }}英语听力统计</title><h1>{{ date }}英语听力统计</h1>{% if havedate==True %}{% for c in classes %}<h4>截至到{{ time }}为止</h4><h4>{{ c.get('class') }}班未提交:共{{ c.get('no_s_p') }}人</h4><h4>分别为:{{ c.get('no_s_p_list') }}</h4><h4></h4><h4></h4><h4>{{ c.get('class') }}班已提交:共{{ c.get('s_p') }}人</h4><h4>分别为:{{ c.get('s_p_list') }}</h4><h3>{{ c.get('class') }}班今日提交饼状图:</h3><h3><img src="{{ c.get('pie') }}" alt="饼状图加载失败" width="320" height="240"></h3><h3>{{ c.get('class') }}班最近几日提交对比:</h3><h3><img src="{{ c.get('bar') }}" alt="柱状图加载失败" width="320" height="240"></h3>{% endfor %}{% else %}<h1>今天还没有人打卡哦 等等再来吧</h1>{% endif %}<input type="button" value="返回" onclick="location.reload();">
</head>
<body></body>
</html>
如图
3. 关于页面
文件:help.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>关于</title><h4>别看了 网站是3.7周景鑫写的 长按加我vx</h4><img src="static\vx.jpg" alt="二维码加载失败" width="180" height="264"/><h4></h4>{% for info in infolist %}<h6>更新日志:{{ info['time'] }}</h6><h6>{{ info['info'] }}</h6>{% endfor %}<h4>------------------------------</h4><h4> </h4><h6>由于技术与时间等原因 不足之处敬请谅解</h6><h6>出现问题请联系周景鑫 vx:zjxyyds0307</h6><h2>别看了快去学习吧</h2><input type="button" value="返回" onclick="location.reload();">
</head>
<body></body>
</html>
如图
4. 彩蛋(直接copy的)
看图
这两个,都是抄的,就不放代码了…
5. 猜成语
转型之路了属于是
代码:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>无奖成语竞猜</title><script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script><h3 style="text-align:center">根据意思猜成语</h3><h4 id="t">成语意思和解释</h4><h4 id="question">-</h4><h4 id="fig1"> </h4><h4 id="quanpin"> </h4><h4 id="ts">请输入成语:</h4><input type="text" id="input" placeholder="输入成语"><h4> </h4><h4 id="ans"> </h4><h4 id="chuchu"> </h4><h4 id="liju"> </h4><button onclick="send()" id="send">提交一下</button><button onclick="fig_fun()" id="fig_b">提示</button><h4> </h4><input type="button" value="返回" onclick="location.reload();"><h6>成语数据由天行api提供</h6><script>window.onload = load_all();const ans = "答案: {{ answer }}";const sp = "首拼: {{ sp }}";// 首拼const source = "出处: {{ source }}";// 出处const study = "例句: "+"{{ study }}";// 例句var fig_flag = 0;function load_all(){$("#question").text("{{ question }}");}function ok(){$("#ans").text(ans);$("#question").text("词义是: {{ question }}");$("#chuchu").text(source);$("#liju").text(study);$("#send").hide();$("#fig_b").hide();$("#input").hide();$("#ts").hide();$("#t").hide();$("#fig1").hide();}function fig_fun(){if(fig_flag == 2){// console.log(ans);ok();}else if(fig_flag == 1){$("#quanpin").text('全拼: {{ quanpin }}');fig_flag = fig_flag + 1;$("#fig_b").text("告诉我答案");}else{fig_flag = fig_flag + 1;$("#fig1").text(sp);$("#fig_b").text("再提示一下");}}function send(){if($("#input").val() == "{{ answer }}"){alert("恭喜 答对了");ok();}else{alert("还不对哦 再试试");}}</script>
</head>
<body></body>
</html>
如图:
四、写后端
1. app.py
代码:
import http.client, urllib, json
import random
from flask import *
from sql_fun import *app = Flask(__name__)
sql_f = mess_sql()class info:def __init__(self):self.c = sql_f.new_statistics()sql_f.close_sql()i = info()@app.route('/')
def hello_world(): # put application's code herereturn render_template("main.html",date=get_today(),name=sql_f.ip_to_name(request.remote_addr))@app.route('/add', methods=["POST"])
def add_fun():name = str(request.form.get("name"))vid = str(request.form.get("vid"))print('vid:', vid)ans = sql_f.add(name, request.remote_addr, vid)sql_f.close_sql()if '打卡成功' in ans:i.c = sql_f.new_statistics()# 在这里画图sql_f.close_sql()return {'message': ans}@app.route('/about', methods=['POST'])
def helpfun():sql_f.add_visit(request.remote_addr, 'help')infol = []with open('helplist.txt', 'r', encoding='utf-8') as f:infolist = f.readlines()index = 0m = {}for i in infolist:index += 1if index % 2 == 0:m['info'] = iinfol.append(m)m = {}else:m['time'] = i# return render_template('help.html')return render_template('help.html', infolist=infol)@app.route('/heart', methods=['POST'])
def heart_fun():name = str(request.form.get("name"))a = random.randint(0,9)if name == '' or name == ' ':name = '专属于你'if a > 6:sql_f.add_visit(request.remote_addr, name + ':heart')print(name + ':heart')return render_template('heart.html', name=name)else:sql_f.add_visit(request.remote_addr, name + ':圣诞树')print(name + ':圣诞树')return render_template('圣诞树.html', name=name)@app.route('/s', methods=['POST'])
def s():print(request.remote_addr + ':statistics')sql_f.add_visit(request.remote_addr, 'statistics')return render_template('statistics.html',date=get_today(),havedate=sql_f.today_date_have(),classes=i.c,time=datetime.datetime.now().strftime('%H:%M:%S'))def get_p_dic():conn = http.client.HTTPSConnection('apis.tianapi.com') # 接口域名params = urllib.parse.urlencode({'key': '天行数据api的key'})headers = {'Content-type': 'application/x-www-form-urlencoded'}conn.request('POST', '/caichengyu/index', params, headers)tianapi = conn.getresponse()result = tianapi.read()data = result.decode('utf-8')dict_data = json.loads(data)return dict_datadef is_None(s):if s == '':return '暂无'return s@app.route('/p', methods=['POST', 'GET'])
def p():d = get_p_dic()print(d)print(request.remote_addr + ':猜成语')sql_f.add_visit(request.remote_addr, '猜成语')sql_f.add_phrase(d)return render_template("phrase.html",question=d.get("result").get("question"),answer=d.get("result").get("answer"),source=is_None(d.get("result").get("source")),study=is_None(d.get("result").get("study")),sp=d.get("result").get("abbr"),quanpin=d.get("result").get("pinyin"))if __name__ == '__main__':app.run()
其实也写了一些没有意义的代码 (某种程度上)
这个是程序入口,使用的flask框架
为什么 将画图部分移动到添加信息过程
- 提高用户体验:打卡过程中按钮会禁用一段时间(见前端代码),将占用时间的工作放到此过程中非常合适
- 提高用户体验:统计数据时非常快,用户会觉得我代码写的好 ,其实是把费时间工作放到其他地方做了。
2. sql_fun内部
文件: __ init__.py
import pymysql
import datetime
import matplotlib.pyplot as pltdef get_today():return str(datetime.datetime.now().strftime('%Y-%m-%d'))plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.yticks(fontsize=26)
plt.xticks(fontsize=26)class mess_sql:def __init__(self):# self.word_max = 500try:self.connect = pymysql.connect(host='localhost',user='root',password='',db='english punch',charset='gbk') # 服务器名,账户,密码,数据库名称except:self.connect = pymysql.connect(host='localhost',user='root',password='',db='english punch',charset='gbk') # 服务器名,账户,密码,数据库名称self.cur = self.connect.cursor()def open_sql(self):try:self.connect = pymysql.connect(host='localhost',user='root',password='',db='english punch',charset='gbk') # 服务器名,账户,密码,数据库名称except:self.connect = pymysql.connect(host='localhost',user='root',password='',db='english punch',charset='gbk') # 服务器名,账户,密码,数据库名称self.cur = self.connect.cursor()def close_sql(self):try:if self.connect:self.connect.close()if self.cur:self.cur.close()except Exception as e:print(e)def add(self, name, ip, vid):self.open_sql()try:self.connect.ping(reconnect=True)find_name_in_table = "select class from all_name where name='{0}'".format(name)# print("find_name_in_table:", find_name_in_table)self.cur.execute(find_name_in_table)classres = self.cur.fetchall()if len(classres) == 0:s = '{0} 不在班级总名单中哦 检查一下是不是字打错了'.format(name)print(s)self.add_visit(ip, s)return stoday = "select date from update_table where date > '{0}' and name ='{1}'".format(get_today(), name)self.cur.execute(today)res = self.cur.fetchall()if len(res) != 0:s = '今天 {0} 已经打卡了哦 打卡时间为 {1}'.format(name, res[0][0])print(s)self.add_visit(ip, s)return sip_err = "select name from update_table where date > '{0}' and vid='{1}'".format(get_today(), vid)self.cur.execute(ip_err)res = self.cur.fetchall()# TODO 防止重复ipres = []if len(res) != 0:s = "今天本设备已经为 {0} 打卡啦 不能重复打卡".format(res[0][0])print(s)self.add_visit(ip, s)return sadd_text = "insert into update_table values ('{0}','{1}','{2}','{3}','{4}');"\.format(name, classres[0][0],datetime.datetime.now(),ip, vid)self.cur.execute(add_text)self.connect.commit()s = '{0}打卡成功 打卡时间为:{1}'.format(name, datetime.datetime.now().strftime('%H:%M:%S'))print(s)return sexcept Exception as e:print(e)self.add_visit(ip, str(e))return 'E'def new_statistics(self):try:self.open_sql()self.connect.ping(reconnect=True)search_class = 'SELECT class FROM all_name GROUP BY class;'self.cur.execute(search_class)classes = self.cur.fetchall()res_list = []for c in classes:c = c[0]all_name = "select name from all_name where class={0}".format(c)self.cur.execute(all_name)res = self.cur.fetchall()res = [i[0] for i in res] # list(res)tijiao = "select name from update_table where date > '{0}' and class={1}".format(get_today(), c)self.cur.execute(tijiao)tijiao_list = self.cur.fetchall()# tijiao_list = list(tijiao_list)tijiao_list = [i[0] for i in tijiao_list]# print(tijiao_list)yitijiao = len(tijiao_list)weitijiao = len(res) - yitijiaoweitijiao_list = ",".join([i for i in res if i not in tijiao_list])yitijiao_list = ",".join([i for i in tijiao_list])plt.figure()plt.cla()plt.title('提交对比', fontsize=26)plt.pie([weitijiao, yitijiao], labels=['未提交', '已提交'], autopct='%3.1f%%')pie_path = 'static/pie{0}.png'.format(c)plt.savefig(pie_path)# plt.show()bar_path = self.lately(c)plt.close('all')m = {'class': c,'no_s_p': weitijiao,'no_s_p_list': weitijiao_list,'s_p': yitijiao,'s_p_list': yitijiao_list,'pie': pie_path,'bar': bar_path}res_list.append(m)return res_listexcept Exception as e:print(e)self.add_visit('0.0.0.1', str(e))return []def lately(self, c):try:plt.figure(dpi=300, figsize=(10, 10))time_list = []peo_list = []delta = datetime.timedelta(days=-1)endtime = datetime.datetime.now() - deltafor i in range(5):starttime = endtime + delta# print(str(starttime.strftime('%Y-%m-%d')))sql = "select name from update_table where date>'{0}' and date<'{1}' and class={2}".format(starttime.strftime('%Y-%m-%d'),endtime.strftime('%Y-%m-%d'), c)# print('sql line', sql)self.connect.ping(reconnect=True)self.cur.execute(sql)res = self.cur.fetchall()# if len(res) == 0:# endtime = starttime# continuetime_list.append(str(starttime.strftime('%m-%d')))peo_list.append(len(res))endtime = starttimeplt.cla()plt.legend(fontsize=32)plt.title('最近打卡情况对比',fontsize=20)x = [i + 1 for i in range(len(time_list))]color = ['peru', 'orchid', 'deepskyblue']plt.yticks(fontsize=26)plt.xticks(fontsize=26)plt.xlabel('时间', fontsize=26)plt.ylabel('人数', fontsize=26)list.reverse(time_list)list.reverse(peo_list)# time_list = time_list * 2# peo_list = peo_list * 2plt.xticks(x, time_list) # 绘制x刻度标签b = plt.bar(x, peo_list, color=color, width=0.3)plt.bar_label(b, label_type='edge', fontsize=26)save_path = 'static/bar{0}.png'.format(c)try:plt.savefig(save_path)except:plt.savefig('bar.png')return save_pathexcept Exception as e:print(e)self.add_visit('0.0.0.2', str(e))return ''def ip_to_name(self, ip):try:self.open_sql()sql = "select name from update_table where ip='{0}'".format(ip)self.connect.ping(reconnect=True)self.cur.execute(sql)res = self.cur.fetchall()res = [i[0] for i in res] # list(res)res = list(set(res))# print(res)print('返回的记忆用户名' + ','.join(res))self.add_visit(ip, '返回的记忆用户名' + ','.join(res))self.close_sql()return ','.join(res)except Exception as e:print(e)self.add_visit('0.0.0.3', str(e))return ''def today_date_have(self):try:self.open_sql()sql = "select name from update_table where date > '{0}'".format(get_today())self.connect.ping(reconnect=True)self.cur.execute(sql)res = self.cur.fetchall()self.close_sql()return len(res) != 0except Exception as e:print(e)self.add_visit('0.0.0.3', str(e))return Truedef add_visit(self, ip, thing):try:self.open_sql()sql = "insert into visit values ('{0}','{1}','{2}');".format(datetime.datetime.now(),ip,thing)self.connect.ping(reconnect=True)self.cur.execute(sql)self.connect.commit()self.close_sql()except Exception as e:print(e)# self.add_visit('0.0.0.4', str(e))def add_phrase(self, d):try:self.open_sql()question = d.get("result").get("question")answer = d.get("result").get("answer")source = d.get("result").get("source")study = d.get("result").get("study")sp = d.get("result").get("abbr")quanpin = d.get("result").get("pinyin")sql = "insert into phrase values ('{0}','{1}','{2}','{3}','{4}','{5}');".format(question, answer, source, study, sp, quanpin)self.connect.ping(reconnect=True)self.cur.execute(sql)self.connect.commit()self.close_sql()except Exception as e:print(e)self.add_visit('0.0.0.5', str(e))
- open_sql:打开数据库
- close_sql:关闭数据库
- add:添加打卡信息
- new_statistics:统计本日打卡
- lately:统计最近几日打卡人数
- ip_to_name:记忆用户名
- today_date_have:查询今天是否有人已打卡
- add_visit:添加访问记录
- add_phrase:添加一条成语记录
3. helplist.txt
2022-12-02 17:00
添加了"最近几日统计" 增强稳定性
2022-12-03 00:30
添加对代替打卡的防护 同一设备每天只能打卡一人(已停用)
2022-12-03 10:30
根据以前打卡记录自动填充姓名 节省时间(不完全)
2022-12-03 15:00
添加了对班级的管理 方便其他班级的使用
2022-12-03 17:30
添加了小彩蛋
2022-12-04 01:00
修复会将昨天打卡情况显示到今天的问题
2022-12-04 11:30
添加了猜成语功能
2022-12-04 12:40
增强稳定性 修复了进入彩蛋后无法退出的问题 现在进入彩蛋后 点击文字即可退出
2022-12-08 21:40
增强稳定性 修复长时间连接数据库导致的未知错误
2022-12-08 22:50
更新小彩蛋 加入了圣诞树 点击图像可以返回
使用helplist的目的是降低维护成本,不需要每次更新都需要修改h5页面
五、辅助文件
1. run.bat
一键跑项目
@echo off
python -m flask run --host=0.0.0.0 --port=88
2. 项目目录
C:.
│ app.py
│ bar.png
│ helplist.txt
│ run.bat
│
├─sql_fun
│ │ bar.png
│ │ pie.png
│ │ __init__.py
│ │
│ └─__pycache__
│ __init__.cpython-38.pyc
│
├─static
│ bar3.png
│ bar7.png
│ img.png
│ pie3.png
│ pie7.png
│ vx.jpg
│
├─templates
│ heart.html
│ help.html
│ main.html
│ phrase.html
│ statistics.html
│ 圣诞树.html
│
└─__pycache__app.cpython-38.pyc
六、留个地方放项目网址
等项目测试打包好会上传到GitHub或其他网站,链接会放这里。
写在最后:生活不易,高中生也叹气。
如果你觉得有用的话麻烦点个赞,或者扫一扫二维码赞赏一下。
基于python,mysql的学生打卡系统(班级在用)相关推荐
- 基于javaweb+mysql的学生在线选课系统(管理员、教师、学生)
基于javaweb+mysql的学生在线选课系统(管理员.教师.学生) 运行环境 Java≥8.MySQL≥5.7.Tomcat≥8 开发工具 eclipse/idea/myeclipse/sts等均 ...
- 数据库课设--基于Python+MySQL的餐厅点餐系统
文章目录 一.系统需求分析 二.系统设计 1. 功能结构设计 2.概念设计 2.2.1 bill_food表E-R图 2.2.2 bills表E-R图 2.2.3 categories E-R图 2. ...
- 计算机毕业设计源代码Python毕业论文题目基于Python实现的学生在线选课系统[包运行成功]
- 基于javaweb+mysql的学生选课系统(java+javaweb+jdbc)
基于javaweb+mysql的学生选课系统(java+javaweb+jdbc) 运行环境 Java≥8.MySQL≥5.7.Tomcat≥8 开发工具 eclipse/idea/myeclipse ...
- 基于B/S的学生网上考试系统(ssh,mysql)
近年来,互联网在国际上得到了迅猛的发展,基于互联网的各种应用也日益受到人们的重视.基于Web的考试系统正是在这种形势下应运而生的.尽管传统的考试形式应用还非常普遍,但伴随着远程教学的推广普及,作为远程 ...
- kettle大于0的转换成1_第一期实训周:基于Python+MySQL+Kettle+R的某网站数据采集分析...
↓ 基于Python+MySQL+Kettle+R的 某网站数据采集分析 哈喽!各位学员们 咱们第一期课程就要开始了 下面划重点! 一 高校院系 齐鲁工业大学数学与统计学院应用统计系 二 实训日期 2 ...
- 精品基于Python的高校学生职业推荐平台兼职招聘求职
<基于Python的高校学生职业推荐平台的设计和实现>该项目采用技术Python的django框架.mysql数据库 ,项目含有源码.论文.PPT.配套开发软件.软件安装教程.项目发布教程 ...
- 基于JSP+MYSQL的路况信息查询系统
运行环境: Myelipse内置 IDE环境: Myeclipse tomcat环境: Myelipse中内置 硬件环境: windows 7/8/10 2G内存以上(推荐4G,4G以上更好) 主要功 ...
- 基于Python+django的 医院排队叫号系统-计算机毕业设计
项目介绍 随着时代发展,越来越多的人需要到医院进行挂号检查等操作,如果全部都到医院现场挂号,一方面的浪费大量的时间和精力,另一方面是浪费大量的医疗资源,为了能够让患者更加方便的进行挂号,我们通过pyt ...
最新文章
- 微生物组-扩增子16S分析研讨会(2020.1)
- 技术分析:搞懂链路追踪
- Windows 11 新版 22593 发布:文件资源管理器全新主页,开始菜单图标优化
- 带你自学Python系列(二):Python列表总结-思维导图
- 扩展RocketMQ 使其支持任意时间精度的消息延迟
- 系统脆弱性检测 (sysytem vulnerability detection) 的研究分类
- 小米入局区块链,究竟是为了什么?
- fclose会写入硬盘吗 linux_Linux 文件操作总结
- 【linux基础】linux更改python默认版本
- Scrum敏捷开发框架
- 诗经 - 小雅 -采薇
- 网易 Duilib:功能全面的开源桌面 UI 开发框架
- 一个隐藏在角落的文章
- 58天象反入侵体系建设实践
- (方法总结)Python 一行代码提取字符串每个单词首字母的两种方法
- Python使用pypinyin实现中文拼音转换教程
- 500个爆文标题_看了1000个爆文标题,终于发现了这个规律.......
- 2021计算机保研记录总结(已上岸计算所)
- 学生成绩管理系统(通过学号,班级,姓名查询以及其他方法的实现)
- 电子模块|自动升降压电源模块LTC3780
热门文章
- 大学文科生vs大学理科生
- ZooKeeper只完美解决Unable to read additional data from server sessionid 0x0报错问题,并带你深度理解ZooKeeper内部机制之选举机制
- 《那些年啊,那些事——一个程序员的奋斗史》五
- element表格固定高度
- linux中license路径,Elasticsearch安装过程中的license问题解决办法
- 牛客小白月赛5 A	无关(relationship)
- dede织梦html手机模板,dede织梦cms手机站模板制作和调用方法
- 决定你命运的,是趋势判断力
- 如何评价《Big Data:大数据时代》这本书?
- QuickMark: ElasticSearch curl command