jailly

需求



主题:学员管理系统

需求:

用户角色,讲师\学员, 用户登陆后根据角色不同,能做的事情不同,分别如下

讲师视图
  管理班级,可创建班级,根据学员qq号把学员加入班级
  可创建指定班级的上课纪录,注意一节上课纪录对应多条学员的上课纪录, 即每节课都有整班学员上, 为了纪录每位学员的学习成绩,需在创建每节上课纪录是,同时 为这个班的每位学员创建一条上课纪录
  为学员批改成绩, 一条一条的手动修改成绩

学员视图
提交作业
查看作业成绩
一个学员可以同时属于多个班级,就像报了Linux的同时也可以报名Python一样, 所以提交作业时需先选择班级,再选择具体上课的节数
附加:学员可以查看自己的班级成绩排名


实现需求



 

  1. 实现全部需求

 

目录结构



学员管理系统
├ bin # 执行文件目录
| └ student_management.py # 执行程序
├ conf # 配置文件目录
| └ setting.py # 配置文件,目前主要保存mysql数据库相关信息
└ core # 程序核心代码位置
├ main.py # 主交互逻辑
├ orm_base.py # 构建映射mysql相关table的类
├ student.py # 学员接口的交互逻辑
└ teacher.py # 讲师接口的交互逻辑

 代码


 1 #! /usr/bin/env python3
 2 # -*- coding:utf-8 -*-
 3 # Author:Jailly
 4 
 5 import os,sys
 6 
 7 BasePath = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 8 sys.path.insert(0,BasePath)
 9 
10 from core import main
11 
12 main.main()
student_management.py
1 db_user = \'jailly\'
2 # db_user = \'root\'
3 db_password = \'123456\'
4 db_host = \'192.168.18.244\'
5 # db_host = \'localhost\'
6 db_port = 3306
7 db_name = \'student_management\'
setting.py
 1 #! /usr/bin/env python3
 2 # -*- coding:utf-8 -*-
 3 # Author:Jailly
 4 
 5 import os,sys
 6 
 7 BasePath = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 8 sys.path.insert(0,BasePath)
 9 
10 from core import teacher
11 from core import student
12 
13 
14 def main():
15     while 1:
16         print(\'\'\'Interface:
17         1.Teacher
18         2.Student\'\'\')
19 
20         role = input(\'Please select your identity:\').strip()
21 
22         if role == \'1\':
23             teacher.main()
24         elif role == \'2\':
25             student.main()
26         else:
27             print(\'\033[1;31mThe identity that you chose does not exist,please select again\033[0m\')
28 
29 if __name__ == \'__main__\':
30     main()
main.py
 1 #! /usr/bin/env python3
 2 # -*- coding:utf-8 -*-
 3 # Author:Jailly
 4 
 5 import sqlalchemy
 6 import os
 7 import sys
 8 from sqlalchemy import create_engine,Column,String,Integer,Enum,and_,or_,func,ForeignKey
 9 from sqlalchemy.ext.declarative import declarative_base
10 from sqlalchemy.orm import sessionmaker,relationship
11 
12 BasePath = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
13 sys.path.insert(0,BasePath)
14 
15 from conf import setting
16 db_user = setting.db_user
17 db_password = setting.db_password
18 db_host = setting.db_host
19 db_port = setting.db_port
20 db_name = setting.db_name
21 
22 engine = create_engine(\'mysql+pymysql://%s:%s@%s:%s/%s?charset=utf8\'%(db_user,db_password,db_host,db_port,db_name),
23                        encoding = \'utf-8\',
24                        echo=False)
25 
26 Base = declarative_base()
27 
28 class Student(Base):
29     __tablename__ = \'student\'
30     id = Column(Integer,primary_key=True)
31     _class = Column(String(64),nullable=False)
32     qq = Column(Integer,nullable=False)
33 
34     def __repr__(self):
35         return \'%s , Class:%s , QQ:%s\'%(self.id,self._class,self.qq)
36 
37 
38 class StudyRecord(Base):
39     __tablename__ = \'study_record\'
40     id = Column(Integer,primary_key=True)
41     day = Column(Integer,nullable=False)
42     homework = Column(Enum(\'Y\',\'N\'),nullable=False,default=\'N\')
43     status = Column(Enum(\'Y\',\'N\'),nullable=False,default=\'Y\')
44     score = Column(Integer)
45     sid = Column(Integer,ForeignKey(\'student.id\'))
46 
47     student = relationship(\'Student\',backref=\'study_record\')
48 
49     def __repr__(self):
50         return \'%s , Day:%s , Status:%s , Score:%s , Sid:%s\'%(self.id,self.day,self.status,self.score,self.sid)
51 
52 Base.metadata.create_all(bind=engine)
orm_base
student.py 
  1 #! /usr/bin/env python3
  2 # -*- coding:utf-8 -*-
  3 # Author:Jailly
  4 
  5 from sqlalchemy import and_
  6 from sqlalchemy.orm import sessionmaker
  7 import os,sys
  8 
  9 BasePath = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 10 sys.path.insert(0,BasePath)
 11 
 12 from core import orm_base
 13 
 14 SessionClass = sessionmaker(bind=orm_base.engine)
 15 session = SessionClass()
 16 
 17 
 18 def insert_student(_class):
 19     \'\'\'
 20     操作student表的函数之一,用来让讲师向班级中添加学员qq
 21     :param _class: 班级名称,对应 student 表中的 _class 字段
 22     :return:
 23     \'\'\'
 24 
 25 
 26     qqs = input(\'请输入您要添加的学员qq(指定多个qq,请以半角逗号分隔):\').strip()
 27     qqs = qqs.split(\',\')
 28     for qq in qqs[:]:
 29         qq = qq.strip()
 30         if qq.isdigit():
 31             qq = int(qq)
 32             if session.query(orm_base.Student).filter(and_(orm_base.Student._class == _class , orm_base.Student.qq == qq))\
 33                     .first():
 34                 print(\'\033[1;31m警告:学员qq \033[1;32m%s\033[0m 在班级 \033[1;32m%s\033[0m 中已存在,请不要重复添加!\033[0m\'%(qq,_class))
 35                 qqs.remove(qq)
 36             else:
 37                 session.add(orm_base.Student(_class=_class,qq=qq))
 38         else:
 39             print(\'\033[1;31m警告:%s 包含非数字字符,无法添加\'%qq)
 40             qqs.remove(qq)
 41 
 42     session.commit()
 43 
 44     if qqs:  # 只有当用户添加的学员qq中至少有一个班级中原本并不存在时,才打印以下提示信息
 45         print(\'已向班级 \033[1;32m%s\033[0m 中成功添加学员qq:\033[1;32m%s\033[0m\'%(_class,\',\'.join([qq.strip() for qq in qqs])))
 46 
 47     input(\'\n请输入回车键继续...\')
 48 
 49 def delete_student(_class):
 50     \'\'\'
 51     操作student表的函数之一,用来让讲师从班级中删除学员qq
 52     :param _class: 班级名称,对应 student 表中的 _class 字段
 53     :return:
 54     \'\'\'
 55 
 56     qqs = input(\'请输入您要删除的学员qq(指定多个qq,请以半角逗号分隔):\').strip()
 57     qqs = qqs.split(\',\')
 58     for qq in qqs[:]:
 59         qq = qq.strip()
 60 
 61         # 虽然理论上一个班级里学员qq是唯一的,但为避免意外情况(如不是通过本程序而是直接操作mysql向同一个班级里添加了2个相同的qq),这里取能够查
 62         # 询到的所有结果组成的列表
 63         students = session.query(orm_base.Student).filter(and_(orm_base.Student._class == _class , orm_base.Student.qq
 64                                                                == qq)).all()
 65         if students:
 66             for student in students:
 67                 session.delete(student)
 68         else:
 69             print(\'\033[1;31m警告:班级 %s 中不存在 学员qq %s\033[0m\'%(_class,qq))
 70             qqs.remove(qq)
 71 
 72     session.commit()
 73 
 74     if qqs:  # 只有当用户删除的学员qq中至少有一个班级中原本存在时,才打印以下提示信息
 75         print(\'已从班级 \033[1;32m%s\033[0m 中成功删除学员qq:\033[1;32m%s\033[0m\'%(_class,\',\'.join([qq.strip() for qq in qqs])))
 76 
 77     input(\'\n请输入回车键继续...\')
 78 
 79 
 80 def update_student(_class):
 81     \'\'\'
 82     操作student表的函数之一,用来让讲师修改班级中的学员qq
 83     :param _class: 班级名称,对应 student 表中的 _class 字段
 84     :return:
 85     \'\'\'
 86 
 87     old = input(\'原学员qq:\').strip()
 88 
 89     # 虽然理论上一个班级里学员qq是唯一的,但为避免意外情况(如不是通过本程序而是直接操作mysql向同一个班级里添加了2个相同的qq),这里取能够查
 90     # 询到的所有结果组成的列表
 91     students = session.query(orm_base.Student).filter(and_(orm_base.Student.qq == old , orm_base.Student._class ==
 92                                                            _class)).all()
 93     if students:
 94         new = input(\'新学员qq:\').strip()
 95         for student in students:
 96             student.qq = new
 97 
 98         session.commit()
 99 
100         print(\'原学员qq: \033[1;32m%s\033[0m 已修改为 \033[1;32m%s\033[0m\'%(old,new))
101 
102     else:
103         print(\'\033[1;31m在班级 \033[1;32m%s\033[0m 中不存在学员qq:\033[1;32m%s\033[0m \033[0m\'%(_class,old))
104 
105     input(\'\n请输入回车键继续...\')
106 
107 
108 def select_student(_class):
109     \'\'\'
110     操作student表的函数之一,用来让讲师查看班级中的学员qq
111     :param _class: 班级名称,对应 student 表中的 _class 字段
112     :return:
113     \'\'\'
114 
115     qqs = session.query(orm_base.Student.qq).filter(orm_base.Student._class == _class).all()
116     print(\'班级 \033[1;32m%s\033[0m 中的所有学员qq:\'%_class)
117     for qq in qqs:
118         print(qq[0])
119 
120     input(\'\n请输入回车键继续...\')
121 
122 
123 def class_manage(_class,scenes):
124     \'\'\'
125     整合了讲师管理班级的各种操作,通过调用对应的函数来实现对 student 表的增删改查
126     :param _class: 班级名称,对应 student 表中的 _class 字段
127     :param scenes: 调用场景,目前仅支持2个值。‘1’ 指代创建班级之后的调用场合;\'2\' 指代手动选择\'管理班级\'选项之后的调用场合
128     :return:
129     \'\'\'
130 
131     if scenes == 1:
132         print(\'班级 \033[1;32m%s\033[0m 已创建,现在您可以-->\' % _class)
133     elif scenes == 2:
134         print(\'已选择班级 \033[1;32m%s\033[0m ,现在您可以-->\' % _class)
135 
136     while 1:
137         print(\'\'\'------- 管理班级 -------
138 1.添加学员qq
139 2.删除学员qq
140 3.修改学员qq
141 4.查看学员qq
142 5.返回上一级
143 6.退出系统\'\'\'
144               )
145 
146         choice = input(\'请选择:\').strip()
147         if choice == \'1\':
148             insert_student(_class)
149 
150         elif choice == \'2\':
151             delete_student(_class)
152 
153         elif choice == \'3\':
154             update_student(_class)
155 
156         elif choice == \'4\':
157             select_student(_class)
158 
159         elif choice == \'5\':
160             if not session.query(orm_base.Student).filter(orm_base.Student._class == _class).all():
161                 if scenes == 1:
162                     print(\'\033[1;31m%s 班中还未添加任何学员,该班级将不会创建\033[0m\')
163                 elif scenes == 2:
164                     print(\'\033[1;31m%s 班中已没有任何学员,该班记录将自动删除\033[0m\')
165 
166             break
167         elif choice == \'6\':
168             if not session.query(orm_base.Student).filter(orm_base.Student._class == _class).all():
169                 if scenes == 1:
170                     print(\'\033[1;31m%s 班中还未添加任何学员,该班级将不会创建\033[0m\')
171                 elif scenes == 2:
172                     print(\'\033[1;31m%s 班中已没有任何学员,该班记录将自动删除\033[0m\')
173 
174             exit()
175         else:
176             print(\'该选项不存在,请重试!\')
177 
178 
179 def create_record(_class,day):
180     \'\'\'
181     创建上课记录
182     :param _class: 班级名称,对应 student 表中的 _class 字段
183     :param day: 第几天,对应 study_record 表中的 day 字段
184     :return:
185     \'\'\'
186 
187     ids = session.query(orm_base.Student.id).filter(orm_base.Student._class == _class).all()
188     records = []
189     for id in ids:
190         records.append(orm_base.StudyRecord(day=day, sid=id[0]))
191 
192     session.add_all(records)
193     session.commit()
194 
195 
196 def record_operation(type):
197     \'\'\'
198     整合了对上课记录的操作,包括创建上课记录和管理上课记录2种
199     :param type: 用来指定操作类型,目前仅支持2个值: \'1\'.创建上课记录;\'2\'.管理上课记录
200     :return:
201     \'\'\'
202 
203     # 第一级无限循环:选择班级和第几天
204     while 1:
205         class_dict = {}
206         _classes = session.query(orm_base.Student._class).group_by(orm_base.Student._class).all()
207 
208         n = 1
209         print(\'---- 班级列表 ----\')
210         for c in _classes:
211             print(\'%s.%s\' % (n, c[0]))
212             class_dict[n] = c[0]
213             n += 1
214         print(\'\')
215 
216         choice_class = input(\'请选择班级:\').strip()
217         day = input(\'请输入第几天:\').strip()
218 
219         if choice_class.isdigit():
220             choice_class = int(choice_class)
221 
222             if 1 <= choice_class < n:
223                 _class = class_dict[choice_class]
224 
225                 # 创建上课记录
226                 if type == 1:
227 
228                     if day.isdigit():
229                         original_records = session.query(orm_base.StudyRecord).filter(and_(orm_base.StudyRecord.day ==
230                            day,orm_base.StudyRecord.sid == orm_base.Student.id,orm_base.Student._class == _class)).all()
231 
232                         if original_records:
233                             overwritten = input(\'班级 \033[1;32m%s\033[0m 第 \033[1;32m%s\033[0m 天的记录已存在,要覆盖吗?\
234 (\\'N\\':不覆盖;其他:覆盖)\'% (_class, day))
235 
236                             if overwritten.upper() == \'N\':
237                                 input(\'已放弃创建(按回车继续...)\')
238                             else:
239                                 for r in original_records:
240                                     session.delete(r)
241 
242                                 create_record(_class,day)
243                                 input(\'已重新创建 \033[1;32m%s\033[0m 班第 \033[1;32m%s\033[0m 天的上课记录(按回车继续...)\'%(_class,day))
244 
245                         else:
246                             create_record(_class,day)
247 
248                             input(\'班级 \033[1;32m%s\033[0m 第 \033[1;32m%s\033[0m 天的上课记录已创建(输入回车键继续...)\' % (_class, day))
249 
250                         break
251                     else:
252                         print(\'\033[1;31m必须输入数字,请重试\033[0m\')
253 
254                 # 修改上课记录
255                 elif type == 2:
256 
257                     if day.isdigit():
258                         # records = session.query(orm_base.StudyRecord).filter(and_(orm_base.StudyRecord.day == day,orm_base.StudyRecord.sid == orm_base.Student.id,orm_base.Student._class == _class)).all()
259                         records = session.query(orm_base.StudyRecord).join(orm_base.Student).filter(and_(
260                             orm_base.Student._class == _class,orm_base.StudyRecord.day == day)).all()
261                         if records:
262 
263                             # 第二级无限循环:显示选定的上课记录,让用户选择操作
264                             while 1:
265                                 print(\'\n------- \033[1;32m%s\033[0m 班第 \033[1;32m%s\033[0m 天上课记录 -------- \
266                                       \n序号    学员qq    第几天    出勤状态    成绩\' %(_class, day))
267 
268                                 n = 1
269                                 record_dict = {}
270                                 for r in records:
271                                     print(str(n).ljust(8),
272                                           str(r.student.qq).ljust(8),
273                                           day.ljust(8),
274                                           (\'出勤\' if r.status == \'Y\' else \'缺勤\').ljust(8),
275                                           str(r.score).ljust(8))
276                                     record_dict[n] = r
277                                     n += 1
278 
279                                 num_chosen = input(\'请选择您要修改的上课记录的序号(\\'b\\':返回上一级;\\'q\\':退出系统):\').strip()
280                                 if num_chosen.isdigit():
281                                     num_chosen = int(num_chosen)
282                                     if 1 <= num_chosen < n:
283                                         record_chosen = record_dict[num_chosen]
284                                         print(\'\'\'您想要:
285     1. 批改成绩
286     2. 修改出勤状态                                        
287     3. 返回上一级
288     4. 退出系统
289                                         \'\'\')
290 
291                                         operation_chosen = input(\'请选择:\').strip()
292 
293                                         # 批改成绩
294                                         if operation_chosen == \'1\':
295                                             while 1:
296                                                 _score = input(\'请输入成绩:\').strip()
297                                                 if _score.isdigit():
298                                                     record_chosen.score = _score
299                                                     session.commit()
300 
301                                                     print(\'已将 \033[1;32m%s\033[0m 班学员 \033[1;32m%s\033[0m 第 \
302 \033[1;32m%s\033[0m 天的成绩修改为 \033[1;32m%s\033[0m\'%(_class,record_chosen.student.qq,day,_score))
303 
304                                                     input(\'\n按回车键继续...\')
305 
306                                                     break
307 
308                                                 else:
309                                                     print(\'\033[1;31m成绩必须为整数,请重新输入\033[0m\')
310 
311 
312                                         # 修改出勤状态
313                                         elif operation_chosen == \'2\':
314                                             _status = input(\'将出勤状态修改为(N:缺勤;其他:出勤):\').strip()
315                                             if _status.upper() == \'N\':
316                                                 record_chosen.status = \'N\'
317                                             else:
318                                                 record_chosen.status = \'Y\'
319 
320                                             session.commit()
321 
322                                             print(\'已将 \033[1;32m%s\033[0m 班学员 \033[1;32m%s\033[0m 第 \
323 \033[1;32m%s\033[0m 天的出勤状态修改为 \033[1;32m%s\033[0m\'%(_class,record_chosen.student.qq,day,
324                                                     (\'出勤\' if record_chosen.status == \'Y\' else \'缺勤\')))
325 
326 
327                                         elif operation_chosen == \'3\':
328                                             break
329                                         elif operation_chosen == \'4\':
330                                             exit()
331                                         else:
332                                             input(\'\033[1;31m您的选择不存在,请按回车键重试\033[0m\')
333 
334                                     else:
335                                         input(\'\033[1;31m您选择的上课记录不存在,请按回车键重试\033[0m\')
336 
337                                 elif num_chosen.lower() == \'b\':
338                                     break
339                                 elif num_chosen.lower() == \'q\':
340                                     exit()
341                                 else:
342                                     input(\'\033[1;31m必须输入整数,请按回车键重试\033[0m\')
343 
344                         else:
345                             print(\'\033[1;31m班级 %s 第 %s 天的上课记录不存在,请重试\033[0m\'%(_class,day))
346 
347                         break
348 
349                     else:
350                         print(\'\033[1;31m必须输入数字,请重试\033[0m\')
351 
352                 else:
353                     print(\'\033[1;31mtype参数错误,请检查函数调用\033[0m\')
354 
355             else:
356                 print(\'\033[1;31m您选择的班级不存在,请重新输入\033[0m\')
357 
358         else:
359             input(\'\033[1;31m您选择的班级不存在,请按回车键重试\033[0m\')
360 
361 
362 def main():
363     while 1:
364         print(\'\'\'---------- Options ----------
365 1.创建班级
366 2.管理班级
367 3.创建上课记录
368 4.管理上课记录
369 5.退出系统
370         \'\'\')
371 
372         choice = input(\'请选择您的操作类型:\').strip()
373 
374         if choice == \'1\':
375             _class = input(\'请输入班级名称:\').strip()
376             if session.query(orm_base.Student._class).filter(orm_base.Student._class == _class).first():
377                 print(\'班级 \033[1;32m%s\033[0m 已存在,请不要重复创建\'%_class)
378             elif _class:
379                 class_manage(_class,1)
380             else:
381                 print(\'\033[1;31m班级名称不能为空,请重新选择!\033[0m\')
382 
383         elif choice == \'2\':
384             while 1:
385                 class_dict = {}
386                 _classes = session.query(orm_base.Student._class).group_by(orm_base.Student._class).all()
387 
388                 n = 1
389                 print(\'---- 班级列表 ----\')
390                 for c in _classes:
391                     print(\'%s.%s\'%(n,c[0]))
392                     class_dict[n] = c[0]
393                     n += 1
394                 print(\'\')
395 
396                 operations = [\'返回上一级\',\'退出系统\']
397                 for o in operations:
398                     print(\'\033[1;32m%s\033[0m.\033[1;32m%s\033[0m\' % (n, o))
399                     n += 1
400 
401                 choice_class = input(\'请选择班级:\').strip()
402 
403                 if choice_class.isdigit():
404                     choice_class = int(choice_class)
405                     if 1 <= choice_class < (n-2):
406                         _class = class_dict[choice_class]
407                         class_manage(_class,2)
408                     elif choice_class == (n-2):
409                         break
410                     elif choice_class == (n-1):
411                         exit()
412                     else:
413                         print(\'\033[1;31m您选择的班级不存在,请重新输入\033[0m\')
414 
415                 else:
416                     print(\'\033[1;31m您选择的班级不存在,请重新输入\033[0m\')
417 
418 
419         elif choice == \'3\':
420             record_operation(type=1)
421 
422         elif choice == \'4\':
423             record_operation(type=2)
424 
425         elif choice == \'5\':
426             exit()
427         else:
428             print(\'\033[1;31mm该选项不存在,请重试!\033[0m\')
429 
430 
431 if __name__ == \'__main__\':
432     main()
teacher.py

 

 
 

分类:

技术点:

相关文章: