选课系统---软件开发规范
需求分析
从“学生选课系统” 这几个字就可以看出来,我们最核心的功能其实只有 选课。
角色
学生、管理员
功能
登陆 : 管理员和学生都可以登陆,且登陆之后可以自动区分身份
选课 : 学生可以自由的为自己选择课程
创建用户 : 选课系统是面向本校学生的,因此所有的用户都应该由管理员完成
查看选课情况 :每个学生可以查看自己的选课情况,而管理员应该可以查看所有学生的信息
工作流程
登陆 :用户输入用户名和密码
判断身份 :在登陆成果的时候应该可以直接判断出用户的身份 是学生还是管理员
学生用户 :对于学生用户来说,登陆之后有三个功能
1、查看所有课程
2、选择课程
3、查看所选课程
4、退出程序
管理员用户:管理员用户除了可以做一些查看功能之外,还有很多创建工作
1、创建课程
2、创建学生学生账号
3、查看所有课程
4、查看所有学生
5、查看所有学生的选课情况
6、退出程序
程序设计
对于复杂的功能,我们首先就应该想到面向对象编程。而要想将面向对象的程序开发好,就应该做好类和对象的分析工作。
综上,本程序最基础的分析已经完毕。接下来我们要把所有的类以及其中的属性、方法设计出来
课程
属性:课程名、价格、周期、老师
*课程并没有什么动作,所以我们只设计属性不设计方法。其实这里还可以设计很多属性,比如课程的开始时间、结束时间、教室等等,只要你需要,这些都可以记录下来,但是这里我们为了简化代码,就先不设计这些了。
学生
属性:姓名、所选课程
方法:查看可选课程、选择课程、查看所选课程、退出程序
管理员
属性:姓名
方法:创建课程、创建学生学生账号、查看所有课程、查看所有学生、查看所有学生的选课情况、退出程序
流程图

1 import os 2 import sys 3 4 BaseDir = os.path.dirname(os.path.dirname(__file__)) #路径上翻两层 5 sys.path.append(BaseDir) 6 7 from core import core 8 9 if __name__ == '__main__': 10 core.entry_point()

1 import os 2 # base_path = os.path.dirname(os.path.dirname(__file__)) 3 # userinfo = os.path.join(base_path,r'db\userinfo') 4 # log_path = os.path.join(base_path,r'log\test.log') 5 # course_info = os.path.join(base_path,r'db\course_info') 6 # student_info = os.path.join(base_path,r'db\student_info') 7 # level = 'debug'

1 import hashlib 2 from core.log import log 3 from conf.settings import userinfo 4 class Authentic(object): 5 def __init__(self, usr, pwd): 6 self.usr = usr 7 self.pwd = pwd 8 9 def get_md5(self): 10 md5 = hashlib.md5(self.usr.encode('utf-8')) 11 md5.update(self.pwd.encode('utf-8')) 12 return md5.hexdigest() 13 14 def login(self): 15 with open(userinfo, encoding='utf-8') as f: 16 for line in f: 17 username, password, ident = line.strip().split('|') 18 if self.usr == username and self.get_md5() == password: 19 return {'result': True, 'identify': ident, 'username': self.usr} 20 else: 21 return {'result': False} 22 23 @classmethod 24 def auth(cls): 25 opt_lst1 = ['登录', '退出'] 26 while True: 27 for index, opt in enumerate(opt_lst1, 1): 28 print(index, opt) 29 num = int(input('请输入你要做的操作 :')) 30 if num == 1: 31 usr = input('username :') 32 pwd = input('password :') 33 obj = cls(usr, pwd) 34 ret = obj.login() 35 if ret['result']: 36 print('登录成功') 37 log.logger.info('%s用户%s登录成功' % (ret['identify'], ret['username'])) 38 return ret 39 else: 40 print('登录失败') 41 elif num == 2: 42 exit()

1 import sys 2 3 from core.log import log 4 from core.auth import Authentic 5 from core.user import Student 6 from core.user import Manager 7 8 def entry_point(): 9 ret = Authentic.auth() 10 if ret['result']: 11 if hasattr(sys.modules[__name__], ret['identify']): 12 cls = getattr(sys.modules[__name__], ret['identify']) 13 obj = cls.init(ret['username']) 14 while True: 15 for index, opt in enumerate(cls.opt_lst, 1): 16 print(index, opt[0]) 17 try: 18 num = int(input('请选择您要操作的序号 :')) 19 if hasattr(obj, cls.opt_lst[num - 1][1]): 20 getattr(obj, cls.opt_lst[num - 1][1])() 21 except ValueError: 22 log.logger.warning('选择序号输入的内容有误')

1 class Course: 2 def __init__(self, name, price, period, teacher): 3 self.name = name 4 self.price = price 5 self.period = period 6 self.teacher = teacher 7 8 def __str__(self): 9 return '%s,%s,%s,%s' % (self.name, self.price, self.period, self.teacher) 10 11 def __repr__(self): 12 return self.name

1 import logging 2 from conf.settings import log_path,level 3 4 class Log(object): 5 if hasattr(logging,level.upper()): 6 level = getattr(logging,level.upper()) 7 else: 8 level = logging.DEBUG 9 def __init__(self, level=level): 10 logger = logging.getLogger() 11 logger.setLevel(level) 12 fh = logging.FileHandler(log_path, encoding='utf-8') 13 ch = logging.StreamHandler() 14 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') 15 fh.setFormatter(formatter) 16 ch.setFormatter(formatter) 17 logger.addHandler(fh) 18 logger.addHandler(ch) 19 self.logger = logger 20 21 log = Log()

1 import os 2 import pickle 3 from core.log import log 4 from core.auth import Authentic 5 from core.course import Course 6 from conf.settings import userinfo,course_info,student_info 7 8 class User(object): 9 @staticmethod 10 def load_obj(file_path): 11 with open(file_path, 'rb') as f: 12 while True: 13 try: 14 obj = pickle.load(f) 15 yield obj 16 except EOFError: 17 break 18 19 @staticmethod 20 def dump_obj(file_path, obj): 21 with open(file_path, 'ab') as f: 22 pickle.dump(obj, f) 23 24 def show_courses(self): # 查看所有课程 25 for count, course in enumerate(self.load_obj(course_info), 1): 26 print('%s %s' % (count, course)) 27 print() 28 29 30 class Manager(User): # 管理员用户 31 opt_lst = [('创建课程', 'create_course'), ('给学生创建账号', 'create_student'), 32 ('查看所有课程', 'show_courses'), ('查看所有学生', 'show_students'), 33 ('查看所有学生的选课情况', 'show_students_courses'), ('退出', 'quit')] 34 35 def __init__(self, name): 36 self.name = name 37 38 def create_course(self): # 创建课程 39 print('in Manager create_course') 40 course_name = input('课程名 :') 41 price = input('课程价格 :') 42 period = input('课程周期 :') 43 teacher = input('授课老师 :') 44 course = Course(course_name, price, period, teacher) 45 # 将课程对象记录到文件 46 self.dump_obj(course_info, course) 47 print('创建%s课程成功\n' % course_name) 48 log.logger.info('%s创建%r课程成功' % (self.name, course)) 49 50 def create_student(self): # 给学生创建账号 51 print('in Manager create_student') 52 username = input('用户名 :') 53 password = input('密码 :') 54 with open(userinfo, 'a', encoding='utf-8') as f: 55 f.write('%s|%s|Student\n' % (username, Authentic(username, password).get_md5())) 56 stu = Student(username) 57 self.dump_obj(student_info, stu) 58 print('创建%s学生账号成功.\n' % username) 59 log.logger.info('%s创建%s学生成功' % (self.name, stu)) 60 61 def show_students(self): # 查看所有学生 62 print('in Manager show_students') 63 for count, stu in enumerate(self.load_obj(student_info), 1): 64 print('%s %s' % (count, stu)) 65 print() 66 67 def show_students_courses(self): # 查看所有学生的选课情况 68 print('in Manager show_students_courses') 69 for count, stu in enumerate(self.load_obj(student_info), 1): 70 name_lst = [course.name for course in stu.courses] 71 print('%s %s : %s' % (count, stu, ','.join(name_lst))) 72 print() 73 74 @classmethod 75 def init(cls, username): 76 manager = cls(username) 77 return manager 78 79 def quit(self): 80 exit() 81 82 83 class Student(User): 84 opt_lst = [('查看所有课程', 'show_courses'), ('查看已选课程', 'show_selected_course'), 85 ('选择课程', 'choose_course'), ('退出', 'quit')] 86 87 def __init__(self, name): 88 self.name = name 89 self.courses = [] 90 91 def __str__(self): 92 return self.name 93 94 def show_selected_course(self): # 查看已选课程 95 for index, course in enumerate(self.courses, 1): 96 print('%s %s' % (index, course)) 97 98 def choose_course(self): # 选择课程 99 flag = False 100 self.show_courses() # 1. PYTHON 2.LINUX 101 num = int(input('请输入课程的序号')) # 1 102 for index, course in enumerate(self.load_obj(course_info), 1): 103 if index == num: 104 self.courses.append(course) 105 flag = True 106 break 107 else: 108 print('请输入有效的序号') 109 if flag: 110 print('选课%r成功' % course) 111 with open('student_info.bak', 'wb') as f2: 112 for stu in self.load_obj(student_info): 113 if stu.name == self.name: 114 pickle.dump(self, f2) 115 else: 116 pickle.dump(stu, f2) 117 os.remove(student_info) 118 os.rename('student_info.bak', student_info) 119 log.logger.info('%s选择%r课程成功' % (self.name, course)) 120 121 @classmethod 122 def init(cls, name): 123 for stu in cls.load_obj(student_info): 124 if stu.name == name: 125 return stu 126 127 def quit(self): 128 exit()