女神博客链接:https://www.cnblogs.com/Eva-J/articles/11370946.html
作业博客链接:https://www.cnblogs.com/Eva-J/articles/9239657.html
代码目录结构如下:

流程图如下:

代码如下:
bin目录:
1 # -*- coding: utf-8 -*- 2 __author__ = 'caiqinxiong_cai' 3 # 2019/8/21 14:25 4 import os 5 import sys 6 # 项目工作目录绝对路径 7 base_dir = os.path.dirname(os.path.dirname(__file__)) 8 sys.path.append(base_dir) # 先添加当前工作路径,导入自定义模块时才能生效 9 from conf import settings as ss 10 from core import student as st 11 from core import teacher as tc 12 from core.certification import Certification as cc 13 from core import manager as ad 14 from core.log import Log as log 15 16 if __name__ == '__main__': 17 print("#" * 25 + '\n欢迎来到luffycity选课系统!\n' + "#" * 25) 18 ret = cc().login # 登录校验,返回用户信息 19 if ret in ss.admin_dict: 20 log.info(ret+'管理员登录成功!') 21 ad.Manager(ret).admin_view() # 管理员视图 22 elif ret: 23 if ret[-1] == 'student': 24 log.info(ret[0]+'同学登录成功!') 25 s = st.Students(ret[0], ret[1], ret[2], ret[3], ret[4]) 26 s.student_view() # 学生视图 27 elif ret[-1] == 'teacher': 28 log.info(ret[0]+'讲师登录成功!') 29 t = tc.Teacher(ret[0], ret[1], ret[2], ret[3], ret[4]) 30 t.teacher_view() # 讲师视图
conf目录:
1 # -*- coding: utf-8 -*- 2 __author__ = 'caiqinxiong_cai' 3 # 2019/8/21 10:40 4 import os 5 import time 6 # 管理员账号密码信息,密码已转换为MD5密文。 7 admin_dict = {'admin': '21232f297a57a5a743894a0e4a801fc3', 'xiaoqiang': '202cb962ac59075b964b07152d234b70'} 8 9 # 当前文件工作目录绝对路径 10 base_dir = os.path.dirname(os.path.dirname(__file__)) 11 12 # 数据存储路径 13 db_path = os.path.join(base_dir, 'db') 14 if not os.path.exists(db_path):os.makedirs(db_path) 15 16 # 学生账号信息文件 17 student_file = r'%s/student_info' % db_path 18 19 # 讲师账号信息文件 20 teacher_file = r'%s/teacher_info' % db_path 21 22 # 课程信息文件 23 course_file = r'%s/course_info' % db_path 24 25 # 学生选课信息文件,函数:传入学生姓名。 26 choose_course_path = os.path.join(db_path,'choose_course') 27 if not os.path.exists(choose_course_path):os.makedirs(choose_course_path) 28 choose_course_file = lambda name: r'%s/%s_choose_course_info' % (choose_course_path,name) 29 30 # 班级信息文件,函数:传入教室名称。 31 classroom_path = os.path.join(db_path,'classroom') 32 if not os.path.exists(classroom_path):os.makedirs(classroom_path) 33 classroom_file = lambda classname:r'%s/%s_classroom_info' % (classroom_path,classname) 34 35 # 日志文件路径 36 log_path = os.path.join(base_dir,'log') 37 if not os.path.exists(log_path):os.makedirs(log_path) 38 log_file = r'%s/%s-log' % (log_path,time.strftime('%Y-%m-%d', time.localtime(time.time())))
core目录:
# -*- coding: utf-8 -*- __author__ = 'caiqinxiong_cai' # 2019/8/21 10:37 import pickle import hashlib from conf import settings as ss from core.log import Log as log class Certification: '''登录认证类''' def __init__(self): pass @staticmethod # 类的装饰器,静态方法 没有用到默认参数(self),不能使用类变量和实例变量,实现实例化使用 C().f(),也可以不实例化调用该方法 C.f() def written_information(file_name, content, mode='ab'): '''写入信息''' with open('%s' % file_name, mode='%s' % mode) as f: pickle.dump(content, f) @staticmethod def read_information(file_name): '''读取信息''' try: with open('%s' % file_name, mode='rb') as f: while True: try: r = pickle.load(f) for k, v in r.__dict__.items(): yield k, v # 以迭代器方式返回,节省内存使用 except EOFError: break except: return ("", "") @staticmethod def change_hashlib(password): '''将明文转换成密文''' md5 = hashlib.md5() md5.update(password.encode('utf-8')) ret = md5.hexdigest() return ret @classmethod # 类的装饰器,类方法,该函数只能访问到类的数据属性,不能获取实例的数据属性,默认传参数cls,表示当前所在的类名 def check_user(cls, user, name, kind): '''校验账号''' for k, v in name: if 'username' == k and user == v.split(':')[-1].strip(): passwd = cls.change_hashlib(input('请输入密码 :').strip()) if passwd == name.__next__()[-1].split(':')[-1].strip(): return user, passwd, name.__next__()[-1], name.__next__()[-1], name.__next__()[-1], kind else: log.warning('密码校验失败!') return False @property # 类的装饰器,将一个方法伪装成类的属性来使用,注意:函数没有传入参数时使用 def login(self): '''登录验证''' for i in range(3): # 3次机会 user = input('请输入登录名 :').strip() if user in ss.admin_dict: # 优先校验管理员账号,管理员账号总会比普通账号少嘛。 passwd = self.change_hashlib(input('请输入管理员密码 :').strip()) if ss.admin_dict[user] == passwd: print("*" * 25 + '\n登录成功!%s管理员!' % user) return user else: log.warning('管理员密码校验失败!') continue # 讲师账号校验 teacher = Certification().read_information(ss.teacher_file) # 读取讲师账号信息文件,返回迭代器 ret = self.check_user(user, teacher, 'teacher') if ret: print("*" * 25 + '\n登录成功!%s讲师!' % user) return ret # 学生账号校验 student = Certification().read_information(ss.student_file) # 读取学生账号信息文件,返回迭代器 ret = self.check_user(user, student, 'student') if ret: print("*" * 25 + '\n登录成功!%s同学!' % user) return ret else: print('账号不存在!') else: log.warning('您的3次尝试机会已用完,谢谢使用!') return False if __name__ == '__main__': print(Certification().login)
# -*- coding: utf-8 -*- __author__ = 'caiqinxiong_cai' # 2019/8/21 14:19 class Course(object): '''课程类''' def __init__(self, name, teacher, price, period): self.name = name self.teacher = teacher self.price = price self.period = period class Classroom(object): '''班级类''' def __init__(self, classroom, course, teacher={'讲师信息:':None}, student={'学生信息:':[]}): self.classroom = classroom # 班级名称 self.course = course # 所教课程 self.teacher = teacher # 授课讲师 self.student = student # 学生列表
1 # -*- coding: utf-8 -*- 2 __author__ = 'caiqinxiong_cai' 3 # 2019/8/21 14:20 4 import os 5 import sys 6 import time 7 from conf import settings as ss 8 from core.certification import Certification as cc 9 from core import student as st 10 from core import teacher as tc 11 from core import user as us 12 from core import course as cs 13 from core.log import Log as log 14 15 class Manager(object): 16 '''管理员类''' 17 18 def __init__(self, name): 19 self.name = name 20 21 def __create_account(self,file,kind): 22 '''创建账号,私有方法,只有管理员才能创建。''' 23 while True: 24 username = '*' * 25 + '\n姓名:' + input('please input the username:').strip() 25 ret = cc().read_information(file) 26 for k, v in ret: # 校验账号是否已存在 27 if username in v: 28 log.warning('%s%s账号已存在!!' % (username.split(':')[-1], kind)) 29 break 30 else: 31 __password = '密码:' + cc.change_hashlib(input('please input the password:').strip()) # 将输入的密码转换成密文存储 32 age = '年龄:' + input('please input the age:').strip() 33 sex = '性别:' + input('please input the sex:').strip() 34 phone = '手机号码:' + input('please input the phone number:').strip() 35 print("*" * 25 + '\n\033[31;1m%s账号创建成功!详细信息如下:\033[0m\n%s\n%s\n%s\n%s' % (kind, username, age, sex, phone)) 36 log.info(self.name+'创建'+username.split(':')[-1]+kind+'账号成功!') 37 u = us.User(username, __password, age, sex, phone) 38 cc().written_information(file, u) # 将实例化对象写入文件 39 break 40 41 def create_student_account(self): 42 '''创建学生账号''' 43 print('请添加学生信息!') 44 self.__create_account(ss.student_file, '学生') 45 46 47 def create_teacher_account(self): 48 '''创建讲师账号''' 49 print('请添加讲师信息!') 50 self.__create_account(ss.teacher_file, '讲师') 51 52 53 def view_accout_info(self,file, kind): 54 '''查看账号信息''' 55 if not os.path.exists(file):return log.error('%s文件不存在,还未添加任何%s账号!' % (file,kind)) 56 ret = cc().read_information(file) 57 print('*' * 25 + '\n\033[31;1m所有%s信息如下:\033[0m' % kind) 58 for k, v in ret:log.debug(v) # 打印账号信息 59 60 61 def view_all_students(self): 62 '''查看所有学生''' 63 self.view_accout_info(ss.student_file, '学生') 64 65 66 def view_all_teachers(self): 67 '''查看所有讲师信息''' 68 self.view_accout_info(ss.teacher_file, '讲师') 69 70 71 def create_course(self): 72 '''创建课程''' 73 print('请添加课程信息!') 74 flag = True 75 while flag: 76 name = '*' * 25 + '\n课程名称:' + input('please input the course`s name:').strip() 77 ret = cc().read_information(ss.course_file) 78 for k, v in ret: # 校验课程是否已存在,避免重复创建课程。 79 if name in v: 80 log.error('%s课程已存在!!' % name.split(':')[-1]) 81 break 82 else: 83 teacher = '授课老师:' + input('please input the teacher`s name:').strip() 84 ret = cc().read_information(ss.teacher_file) 85 for k,v in ret: # 校验讲师信息是否存在,否则先添加讲师信息。 86 if teacher.split(':')[-1] in v: 87 price = '课程价格:' + input('please input the course`s price:').strip() 88 period = '课程周期:' + input('please input the period:').strip() 89 print("*" * 25 + '\n\033[31;1m创建课程成功!信息如下:\033[0m\n%s\n%s\n%s\n%s' % (name, teacher, price, period)) 90 log.info(self.name+'创建'+name.split(':')[-1]+'课程成功!') 91 c = cs.Course(name, teacher, price, period) # 将课程信息传入课程类 92 cc().written_information(ss.course_file, c) # 将课程类写入文件 93 flag = False 94 break 95 else: 96 log.warning('授课老师%s不存在!' % teacher.split(':'[-1])[-1]) 97 98 99 def view_all_courses(self): 100 '''查看所有课程''' 101 if not os.path.exists(ss.course_file): return log.warning('课程文件不存在,还未添加任何课程哦!') 102 print('*' * 25 + '\n\033[31;1m所有课程信息如下:\033[0m') 103 ret = cc().read_information(ss.course_file) 104 for k, v in ret:log.debug(v) # 打印所有课程信息 105 106 107 def view_all_selected_courses(self): 108 '''查看所有学生的选课情况''' 109 flag = True 110 for file_name in os.listdir(ss.choose_course_path): # 获取所有的学生选课信息文件 111 if 'choose_course_info' in file_name: 112 print('*' * 25 + '\n\033[31;1m%s所选课程信息如下:\033[0m' % file_name.split('_')[0]) 113 ret = cc().read_information(ss.choose_course_file(file_name.split('_')[0])) 114 for k, v in ret:log.debug(v) # 打印所选课程信息 115 flag = False 116 if flag: log.warning('还未有学生选择任何课程哦!') 117 118 119 def create_classroom(self): 120 '''创建班级''' 121 print('请添加班级信息!') 122 while True: 123 classroom = input('请输入教室名称(如:101):').strip() 124 if os.path.exists(ss.classroom_file(classroom)): 125 log.warning('%s教室已存在!!' % classroom) 126 else: 127 classcourse = '班级课程:' + input('请输入班级课程名称:').strip() 128 classroom = '*'*25 + '\n教室名称:' + classroom 129 print('添加班级信息成功!详细信息如下:\n%s\n%s\n讲师信息:None\n学生信息:[]' % (classroom,classcourse)) 130 log.info(self.name+'创建%s教室信息成功!' % classroom.split(':')[-1]) 131 c = cs.Classroom(classroom,classcourse) # 只传入教室和课程名称,学生和讲师使用默认值,等管理员单独指定。 132 cc().written_information(ss.classroom_file(classroom.split(':')[-1]), c) # 将班级信息写入文件 133 break 134 135 136 def view_classroom_info(self): 137 '''查看教室信息''' 138 flag = True 139 for file_name in os.listdir(ss.classroom_path): 140 ret = cc().read_information(os.path.join(ss.classroom_path,file_name)) 141 for k,v in ret:log.debug(v) 142 flag = False 143 if flag:log.warning('还未创建任何教室信息哦!') 144 145 146 def __specified_classroom(self,file,kind): 147 '''指定班级,私有方法,只有管理员才能指定。''' 148 if not os.path.exists(file): return log.warning('还未添加任何%s账号信息,请先添加!' % kind) 149 dir = os.listdir(ss.classroom_path) 150 if not dir:return log.warning('还未添加任何教室信息,请先添加!') # 目录为空 151 flag = True 152 while flag: 153 name = input('请输入%s姓名:' % kind).strip() 154 teacher = cc().read_information(file) 155 for s,t in teacher: 156 if '姓名' in t and name in t: 157 flag = False 158 classroom = input('请输入教室名称(如:101):').strip() 159 for file_name in dir: 160 if classroom in file_name: 161 ret = cc().read_information(ss.classroom_file(classroom)) 162 class_name = ret.__next__()[-1] # 装饰器逐个取值 163 course_name = ret.__next__()[-1] 164 teacher_name = ret.__next__()[-1] 165 student_list = ret.__next__()[-1] 166 if kind == '讲师': 167 teacher_name['讲师信息:'] = name # 指定讲师,一个班只有一个讲师 168 conten = '%s成功将%s讲师分配到%s教室!' % (self.name,name,classroom) 169 else: 170 if name in student_list['学生信息:']: # 一个班里不能重复添加学生信息 171 log.warning('%s已经在%s教室里了哦!' % (name,classroom)) 172 break 173 else: 174 student_list['学生信息:'].append(name) #指定学生,一个班可以有多个学生 175 conten = '%s成功将%s同学分配到%s教室!' % (self.name,name,classroom) 176 log.debug(conten) 177 c = cs.Classroom(class_name, course_name,teacher_name,student_list) 178 cc().written_information(ss.classroom_file(classroom), c, mode='wb') # 将班级信息覆盖写入文件 179 log.info(conten) 180 break 181 else: 182 log.warning('%s教室不存在!!' % classroom.split(':')[-1]) 183 break 184 if flag:log.warning('%s%s不存在!' % (name,kind)) 185 186 187 def classroom_teacher(self): 188 '''为讲师指定班级''' 189 self.__specified_classroom(ss.teacher_file,'讲师') 190 191 192 def classroom_student(self): 193 '''为学生指定班级''' 194 self.__specified_classroom(ss.student_file,'学生') 195 196 197 def quit(self): 198 '''退出程序''' 199 print('\033[31;1m谢谢使用!\033[0m') 200 exit(-1) 201 202 203 def admin_view(self): 204 '''管理员界面''' 205 opt_list = [('创建学生账号','create_student_account'),('查看所有学生信息','view_all_students'),('为学生指定班级','classroom_student'), 206 ('创建讲师','create_teacher_account'),('查看所有讲师信息','view_all_teachers'),('为讲师指定班级','classroom_teacher'), 207 ('创建课程','create_course'),('查看所有课程','view_all_courses'),('查看所有学生的选课情况','view_all_selected_courses'), 208 ('创建班级','create_classroom'),('查看教室信息','view_classroom_info'),('退出','quit')] 209 while True: 210 print('*' * 25) 211 for index,opt in enumerate(opt_list,1):print(index,opt[0]) # 打印操作列表信息 212 try: 213 num = int(input( '*' * 25 + '\n请输入您要选择的操作序号:')) 214 if hasattr(Manager(self.name),opt_list[num-1][1]):getattr(Manager(self.name),opt_list[num-1][1])() # 反射 215 except ValueError as e: 216 log.error('%s不是效数字!!' % e) 217 except IndexError as e: 218 log.error('%s\n请输入1-12的有效数字!!' % e) 219 print('3秒后自动跳转回主页面!') 220 time.sleep(3) 221 222 223 if __name__ == '__main__': 224 Manager('admin').admin_view()
# -*- coding: utf-8 -*- __author__ = 'caiqinxiong_cai' # 2019/8/21 15:39 class User(object): '''用户类,作为学生和讲师的父类,应用公共属性''' def __init__(self, username, password, age, sex, phone): self.username = username self.password = password self.age = age self.sex = sex self.phone = phone
# -*- coding: utf-8 -*- __author__ = 'caiqinxiong_cai' # 2019/8/21 10:36 import os import time from conf import settings as ss from core import certification as cc from core import course as cs from core import user as us from core.log import Log as log class Students(us.User): # 继承父类 '''学生类''' def __init__(self, username, password, age, sex, phone): us.User.__init__(self, username, password, age, sex, phone) def view_optional_courses(self): '''查看可选课程''' if not os.path.exists(ss.course_file): return log.warning('课程文件不存在,还未有可选课程哦!') print('*' * 25 + '\n\033[31;1m所有可选课程信息如下:\033[0m') stu = list(cc.Certification().read_information(ss.choose_course_file(self.username))) ret = cc.Certification().read_information(ss.course_file) for k, v in ret: for s, t in stu: # 只展示该学生未选的课程,已经选过的课就不能再选啦。 if t == v: break else: log.debug(v) def choose_course(self): '''选择课程''' print('请输入选择课程名称:') flag = True while flag: choose = input().strip() ret = cc.Certification().read_information(ss.choose_course_file(self.username)) for k, v in ret: # 已经选过的课程就不能重复选择了。 if choose in v: log.warning('您已经选过%s课程!请重新选择:' % choose) break else: ret = cc.Certification().read_information(ss.course_file) for k, v in ret: # 从剩下的可选课程中选择。 if '课程名称' in v and choose in v: name = v # 将选择的课程信息都写入到该学生的选课文件中。 price = ret.__next__()[-1] period = ret.__next__()[-1] teacher = ret.__next__()[-1] print("*" * 25 + '\n\033[31;1m选择课程成功!详情如下:\033[0m\n%s\n%s\n%s\n%s' % (name, price, period, teacher)) log.info(self.username+'选择%s课程成功!' % choose) c = cs.Course(name, price, period, teacher) # 将课程信息传入课程类 cc.Certification().written_information(ss.choose_course_file(self.username),c) # 将课程类写入文件 flag = False break else: log.warning('选择的%s课程不存在哦!请重新选择:' % choose) def view_selected_courses(self): '''查看所选课程''' if not os.path.exists(ss.choose_course_file(self.username)): return log.warning('您还未选择任何课程哦!') print('*' * 25 + '\n\033[31;1m%s所选课程信息如下:\033[0m' % self.username) ret = cc.Certification().read_information(ss.choose_course_file(self.username)) for k, v in ret:print(v) # 打印课程信息 def student_view(self): '''学生界面''' while True: print('*' * 25 + '\n1、查看可选课程\n2、选择课程\n3、查看已选课程\n4、退出\n' + '*' * 25) choose = input('请选择:').strip() if '1' == choose: # 查看可选课程 self.view_optional_courses() log.info(self.username+'查看了可选的课程!') elif '2' == choose: # 选择课程 self.choose_course() elif '3' == choose: # 查看已选课程 self.view_selected_courses() log.info(self.username+'查看了已选的课程!') elif '4' == choose: print('谢谢使用!') exit(-1) else: print('输入有误,请重新输入!') print('3秒后自动跳转回主页面!') time.sleep(3) if __name__ == '__main__': Students('caiqinxiong','pwd','age','sex','phone').student_view()
# -*- coding: utf-8 -*- __author__ = 'caiqinxiong_cai' # 2019/8/21 15:33 import os import time from conf import settings as ss from core.certification import Certification as cc from core import course as cs from core import user as us from core import manager as ad from core.log import Log as log class Teacher(us.User): # 继承父类 '''讲师类''' def __init__(self, username, password, age, sex, phone): us.User.__init__(self,username, password, age, sex, phone) def classroom_info(self,kind): '''班级信息''' flag = True for file_name in os.listdir(ss.classroom_path): ret = list(cc().read_information(os.path.join(ss.classroom_path,file_name))) if self.username == ret[2][-1]['讲师信息:']: if kind == '讲师': log.debug('%s所教的班级信息如下:\n%s\n%s' % (self.username,ret[0][-1],ret[1][-1])) else: log.debug('%s所教的班级中的学生信息如下:' % (self.username)) log.debug('%s教室共有%s名学生:\n%s' % (ret[0][-1].split(':')[-1],len(ret[-1][-1]['学生信息:']),ret[-1][-1]['学生信息:'])) flag = False if flag: log.warning('%s还未分配任何班级哦,请联系管理员指定。' % self.username) def view_classroom(self): '''查看所教班级''' self.classroom_info('讲师') def view_classroom_student(self): '''查看班级中的学生''' self.classroom_info('学生') def teacher_view(self): '''讲师界面''' while True: print('*' * 25 + '\n1、查看所有课程\n2、查看所教班级\n3、查看班级中的学生\n4、退出\n' + '*' * 25) choose = input('请选择:').strip() if '1' == choose: # 查看所有课程 ad.Manager.view_all_courses(self) # 直接调用管理员的查看所有课程函数即可 log.info(self.username+'查看所有课程!') elif '2' == choose: # 查看所教班级 self.view_classroom() log.info(self.username+'查看了所教班级信息!') elif '3' == choose: # 查看班级中的学生 self.view_classroom_student() log.info(self.username+'查看了TA所教班级中的学生!') elif '4' == choose: print('谢谢使用!') exit(-1) else: print('输入有误,请重新输入!') print('3秒后自动跳转回主页面!') time.sleep(3) if __name__ == '__main__': Teacher('Eva_J','pwd','age','sex','phone').teacher_view()
# -*- coding: utf-8 -*- __author__ = 'caiqinxiong_cai' # 2019/8/26 15:37 import logging import sys import time from logging import handlers from conf import settings as ss class Log(object): ''' https://cloud.tencent.com/developer/article/1354396 ''' now_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) # wh = logging.FileHandler(ss.log_file,encoding='utf-8') # 只写入文件 # logging.getLogger().handlers.append(wh) # logging.getLogger().setLevel(logging.DEBUG) sh = logging.StreamHandler() # 既打印输入又写入文件 # rh = handlers.RotatingFileHandler(ss.log_file, maxBytes=1024,backupCount=5) # 按大小切换日志,保留5份 fh = handlers.TimedRotatingFileHandler(filename=ss.log_file, when='D', backupCount=5, interval=5,encoding='utf-8') # 按时间切割日志 logging.basicConfig(level=logging.WARNING, # 打印日志级别 handlers=[fh, sh], datefmt='%Y-%m-%d %H:%M:%S', format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s') # [%(lineno)d] 只显示当前文件的行号 @classmethod def writeOnly(cls, content): '''自定义函数,只写入日志文件''' with open(ss.log_file, mode='a', encoding='utf-8') as f: f.write(Log.now_time + '\t' + str(content) + '\n') @classmethod def readOnly(cls, content): '''自定义函数,只打印日志''' print('\033[36;1m%s\033[0m' % content) @classmethod def debug(cls, content): # return logging.debug(content) return Log.readOnly(content) @classmethod def info(cls, content): # return logging.info(content) return Log.writeOnly('[INFO]\t' + content) # info信息直接写入log文件 @classmethod def warning(cls, content): return logging.warning(content) @classmethod def error(cls, content): # 获取调用函数的文件名和行数 head = '%s line%s error!\n' % (sys._getframe().f_back.f_code.co_filename, sys._getframe().f_back.f_lineno) return logging.error(head + content) @classmethod def critical(cls, content): head = '%s line%s critical\n' % (sys._getframe().f_back.f_code.co_filename, sys._getframe().f_back.f_lineno) return logging.critical(head + content)
浙公网安备 33010602011771号