module05-2-学员管理系统

需求



主题:学员管理系统

需求:

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

讲师视图
  管理班级,可创建班级,根据学员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

 

 
 
posted @ 2017-09-17 01:41  jailly  阅读(307)  评论(0编辑  收藏  举报