需求
角色:学校、学员、课程、讲师
要求:
1. 创建北京、上海 2 所学校
2. 创建linux , python , go 3个课程 , linux\py 在北京开, go 在上海开
3. 课程包含,周期,价格,通过学校创建课程
4. 通过学校创建班级, 班级关联课程、讲师
5. 创建学员时,选择学校,关联班级
5. 创建讲师角色时要关联学校,
6. 提供两个角色接口
6.1 学员视图, 可以注册, 交学费, 选择班级,
6.2 讲师视图, 讲师可管理自己的班级, 上课时选择班级, 查看班级学员列表 , 修改所管理的学员的成绩
6.3 管理视图,创建讲师, 创建班级,创建课程
7. 上面的操作产生的数据都通过pickle序列化保存到文件里
目录结构
module03-1-选课系统
│
├ bin # 执行文件目录
│ ├ ForAdmin.py # 管理端执行文件
│ ├ ForStudents.py # 学员端执行文件
│ └ ForTeachers.py # 讲师端执行文件
│
├ core # 程序内部逻辑
│ └ main.py # 主逻辑交互程序
│
└ db # 数据库目录
├ init_db.py # 数据库初始化程序
└ school # 数据库文件
代码
1 import os,sys 2 3 base_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 4 core_path = os.path.join(base_path,'core') 5 sys.path.insert(0,core_path) 6 7 import main 8 9 main.admin_int()
1 import os,sys 2 3 base_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 4 core_path = os.path.join(base_path,'core') 5 sys.path.insert(0,core_path) 6 7 import main 8 9 main.student_int()
1 import os,sys 2 3 base_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 4 core_path = os.path.join(base_path,'core') 5 sys.path.insert(0,core_path) 6 7 import main 8 9 main.teacher_int()
1 #! /usr/bin/env python3 2 # -*- coding:utf-8 -*- 3 # Author:Jailly 4 5 import os,pickle,sys,time 6 7 base_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 8 school_file_path = os.path.join(base_path,'db','school') 9 10 class School(object): 11 '''学校类''' 12 13 def __init__(self,name,addr): 14 self.name = name 15 self.addr = addr 16 self.courses = [] 17 self.classes = [] 18 self.teachers = [] 19 self.students = [] 20 21 def create_course(self,name,cycle,price): 22 course = Course(name,cycle,price) 23 self.courses.append(course) 24 25 def create_class(self,num,course,teacher): 26 cls = Cls(num,course,teacher) 27 self.classes.append(cls) 28 29 def create_teacher(self,name): 30 teacher = Teacher(name,self) 31 self.teachers.append(teacher) 32 33 34 class Course(object): 35 '''课程类''' 36 37 def __init__(self,name,cycle,price): 38 self.name = name 39 self.cycle = cycle 40 self.price = price 41 self.cls = None 42 43 44 class Cls(object): 45 '''班级类''' 46 47 def __init__(self,num,course,teacher): 48 self.num = num 49 self.course = course 50 self.teacher = teacher 51 self.students = [] 52 # self.students = list(set(self.students)) 53 54 if course: 55 course.cls = self 56 57 if teacher: 58 teacher.cls = self 59 60 class Teacher(object): 61 '''讲师类''' 62 63 def __init__(self,name,school): 64 self.name = name 65 self.school = school 66 self.cls = None 67 68 69 class Student(object): 70 '''学员类''' 71 72 def __init__(self,name): 73 self.name = name 74 self.courses = [] 75 self.classes = [] 76 77 def enroll(self,school): 78 self.school = school 79 school.students.append(self) 80 81 def pay(self,course): 82 self.courses.append(course) 83 84 def select_cls(self,cls): 85 self.classes.append(cls) 86 # self.classes = list(set(self.classes)) 87 cls.students.append(self) 88 89 90 def save(path,con): 91 '''存储相关数据''' 92 with open(path,'wb') as f: 93 pickle.dump(con,f) 94 95 96 def admin_int(): 97 '''管理接口''' 98 99 while 1: 100 print('''\n--------- 主管理界面 --------- 101 1.创建学校 102 2.进入学校 103 3.退出系统\n''') 104 105 choice = input('请选择您想要进行的操作:').strip() 106 107 if choice == '1': 108 109 # 载入学校信息 110 with open(school_file_path, 'rb') as f: 111 schools_list = pickle.load(f) 112 113 sch_name = input('请输入学校名称:').strip() 114 sch_addr = input('请输入学校地址:').strip() 115 116 if sch_name and sch_addr: 117 sch = School(sch_name,sch_addr) 118 schools_list.append(sch) 119 120 save(school_file_path,schools_list) 121 122 print('\n位于 \033[1;31m%s\033[0m 的学校 \033[1;31m%s\033[0m 已创建成功!\n'%(sch_addr,sch_name)) 123 124 input('请输入任意键按回车继续...') 125 126 else: 127 print('\n\033[1;31m学校名称或地址不能为空!\033[0m\n') 128 129 elif choice == '2': 130 131 # 载入学校信息 132 with open(school_file_path, 'rb') as f: 133 schools_list = pickle.load(f) 134 135 # 输出所有学校名 136 length = len(schools_list) 137 if length: 138 print('\n---- 学校列表 ----') 139 for i in range(length): 140 print( '%s . %s'%(str(i+1),schools_list[i].name) ) 141 142 num = input('\n请选择学校:').strip() 143 144 if num.isdigit(): 145 index = int(num)-1 146 147 if 0 <= index < length: 148 school_int(index) 149 150 else: 151 print('\033[1;31m\n输入的学校编号不存在,请重试!\n\033[0m') 152 153 else: 154 print('\033[1;31m\n输入错误,请重试!\n\033[0m') 155 156 else: 157 print('\033[1;31m\n请先创建一个学校!\n\033[0m') 158 159 # input('请输入任意键按回车继续...') 160 161 elif choice == '3': 162 exit(0) 163 else: 164 print('\033[1;31m输入错误,请重试!\033[0m') 165 166 167 def school_int(index): 168 ''' 169 学校接口 170 param:index:学校对象在学校列表中的索引 171 return:None 172 ''' 173 174 with open(school_file_path, 'rb') as f: 175 school_list = pickle.load(f) 176 177 while 1: 178 print('''\n---- \033[1;36m%s\033[0m 管理界面 ---- 179 1.创建课程 180 2.创建讲师 181 3.创建班级 182 4.学校信息 183 5.返回上一级 184 6.退出系统\n'''%school_list[index].name) 185 186 choice = input('请选择您要进行的操作:').strip() 187 188 # 创建课程 189 if choice == '1': 190 191 with open(school_file_path,'rb') as f: 192 school_list = pickle.load(f) 193 194 while 1: 195 course_name = input('请输入课程名:').strip() 196 course_cycle = input('请输入课程周期(单位:月):').strip() 197 course_price = input('请输入课程价格(单位:元):').strip() 198 199 if course_cycle.isdigit(): 200 course_cycle = int(course_cycle) 201 if course_price.isdigit(): 202 course_price = int(course_price) 203 school_list[index].create_course(course_name,course_cycle,course_price) 204 205 # 将创建了新课程后的学校对象写入对应文件 206 save(school_file_path,school_list) 207 208 print( ' \n在 \033[1;36m%s\033[0m 中创建了新课程 \033[1;36m%s\033[0m ,\ 209 课程周期 \033[1;36m%d\033[0m 个月 ,课程价格 \033[1;36m%d\033[0m 元\n' 210 %(school_list[index].name,course_name,course_cycle,course_price) ) 211 212 input('请输入任意键按回车继续...') 213 214 break 215 else: 216 print('\033[1;31m\n课程价格必须是整数,请重试!\n\033[0m') 217 else: 218 print('\033[1;31m\n课程周期必须是整数,请重试!\n\033[0m') 219 220 221 # 创建讲师 222 elif choice == '2': 223 224 with open(school_file_path,'rb') as f: 225 school_list = pickle.load(f) 226 227 # 判断是否重名 228 229 teacher_name = input('请输入讲师名:').strip() 230 231 for teacher in school_list[index].teachers: 232 if teacher_name == teacher.name: 233 print('\n\033[1;31m讲师 %s 已存在!\033[0m'%(teacher_name)) 234 break 235 else: 236 # 创建讲师 237 school_list[index].create_teacher(teacher_name) 238 239 # 将创建了新讲师后的学校对象写入对应文件 240 save(school_file_path,school_list) 241 242 print( '在 \033[1;36m%s\033[0m 中添加了新讲师 \033[1;36m%s\033[0m'%(school_list[index].name,teacher_name) ) 243 input('\n请输入任意键按回车继续...\n') 244 245 246 # 创建班级 247 elif choice == '3': 248 249 flag = 0 # 课程/讲师创建标记 250 251 with open(school_file_path, 'br') as f: 252 school_list = pickle.load(f) 253 254 # 接收客户输入的班级编号 255 while 1: 256 cls_num = input('请输入班级编号:').strip() 257 258 if cls_num.isdigit(): 259 cls_num = int(cls_num) 260 break 261 else: 262 print('\033[1;31m\n班级编号必须为数字,请重新输入!\n\033[0m') 263 264 # 接收客户输入的班级课程 265 while 1: 266 # 打印课程列表 267 length = len(school_list[index].courses) 268 if length: 269 print('\n---- 课程列表 ----') 270 for i in range(length): 271 print( '%s.%s'%(str(i+1),school_list[index].courses[i].name) ) 272 273 cls_course = input('\n请选择班级课程:').strip() 274 275 if cls_course.isdigit(): 276 cls_course = int(cls_course) - 1 277 278 if 0 <= cls_course < length: 279 cls_course = school_list[index].courses[cls_course] 280 break 281 else: 282 print('\n\033[1;31m您选择的课程不存在,请重新输入!\033[0m\n') 283 284 else: 285 print('\n\033[1;31m只能输入整数,请重试!\033[0m\n') 286 287 else: 288 cls_course = None 289 flag = 1 290 print('\033[1;31m课程不存在,请先创建课程!\033[0m') 291 break 292 293 if flag: 294 input('输入任意键按回车继续...') 295 continue 296 297 # 接收客户输入的班级讲师 298 while 1: 299 length = len(school_list[index].teachers) 300 301 if length: 302 print('\n----讲师列表----') 303 for i in range(length): 304 print( '%s.%s'%(str(i+1),school_list[index].teachers[i].name) ) 305 306 tea = input( '\n请选择班级讲师:').strip() 307 308 if tea.isdigit(): 309 tea = int(tea) - 1 310 if 0 <= tea < length : 311 cls_teacher = school_list[index].teachers[tea] 312 break 313 else: 314 print('\n\033[1;31m您选择的讲师不存在,请重新输入\033[0m\n') 315 316 else: 317 print('\n\033[1;31m只能输入整数,请重试!\033[0m\n') 318 319 320 else: 321 cls_teacher = None 322 flag = 1 323 print('\033[1;31m讲师不存在,请先创建讲师\033[0m') 324 break 325 326 if flag: 327 input('输入任意键按回车继续...') 328 continue 329 330 else: 331 school_list[index].create_class(cls_num,cls_course,cls_teacher) 332 333 save(school_file_path,school_list) 334 335 print( '\n在 \033[1;36m%s\033[0m 中创建了新班级,班级编号 \033[1;36m%d\033[0m ,\ 336 班级课程 \033[1;36m%s\033[0m ,班级讲师 \033[1;36m%s\033[0m \n' 337 %(school_list[index].name,cls_num, 338 cls_course.name if cls_course else '\033[1;36m未定义\033[0m', 339 cls_teacher.name if cls_teacher else '\033[1;36m未定义\033[0m') ) 340 341 input('\n请输入任意键按回车继续...\n') 342 343 # 显示信息 344 elif choice == '4': 345 346 with open(school_file_path, 'rb') as f: 347 school_list = pickle.load(f) 348 349 print('\n \033[1;32m%s\033[0m'%school_list[index].name) 350 # 显示课程 351 print('│\n├ 课程:') 352 if school_list[index].courses: 353 for course in school_list[index].courses: 354 print( '│\t└ %s:'%course.name ) 355 print( '│\t\t├ 课程周期:%s个月'%(course.cycle) ) 356 print( '│\t\t└ 课程价格:%s元'%(course.price)) 357 358 # 显示讲师 359 print('│\n├ 讲师:') 360 if school_list[index].teachers: 361 for teacher in school_list[index].teachers: 362 print( '│\t└ %s'%teacher.name ) 363 print( '│\t\t└ 讲师班级:%s 班'%(teacher.cls.num if teacher.cls else '\033[1;31m未定义\033[0m') ) 364 365 # 显示班级 366 print('│\n└ 班级:') 367 if school_list[index].classes: 368 for cls in school_list[index].classes: 369 print( '\t└ %s 班'%cls.num ) 370 print( '\t\t├ 班级课程:%s'%(cls.course.name if cls.course else '\033[1;31m未定义\033[0m') ) 371 print( '\t\t├ 班级讲师:%s'%(cls.teacher.name if cls.teacher else '\033[1;31m未定义\033[0m') ) 372 print( '\t\t└ 班级学员:%s'%(','.join(list(map(lambda x:x.name,cls.students))) if cls.students else '\033[1;31m未定义\033[0m') ) 373 374 input('\n请输入任意键按回车继续...\n') 375 376 elif choice == '5': 377 break 378 379 elif choice == '6': 380 exit() 381 382 else: 383 print('\033[1;31m输入错误,请重试!\033[0m') 384 385 386 def teacher_int(): 387 ''' 388 讲师接口 389 param: 390 return:None 391 ''' 392 393 with open(school_file_path,'rb') as f: 394 school_list = pickle.load(f) 395 396 while 1: 397 name = input('请输入您的用户名:').strip() 398 399 for school in school_list: 400 for teacher in school.teachers: 401 if name == teacher.name: 402 print('\n\033[1;36m%s\033[0m 老师,欢迎您进入系统!'%name) 403 while 1: 404 print('''\n----操作菜单---- 405 1.查看班级 406 2.查看班级学员 407 3.退出系统''') 408 409 choice = input('请选择操作类型:').strip() 410 if choice == '1': 411 if teacher.cls: 412 print('\n\033[1;36m您所在的班级为 %d 班\033[0m'% teacher.cls.num ) 413 else: 414 print('\n\033[1;31m您的班级还未设置,请联系管理员处理!\033[0m!\n') 415 416 elif choice == '2': 417 print('您所在的班级 %d班 中有如下学员:'%(teacher.cls.num)) 418 if teacher.cls.students: 419 # for student in teacher.cls.students: 420 # print(student.name,end=',') 421 print(','.join( map(lambda x:x.name,teacher.cls.students) )) 422 423 else: 424 print('\n\033[1;31m尚未有学员加入该班级!\033[0m\n') 425 426 elif choice == '3': 427 exit() 428 else: 429 print('\n\033[1;31m用户名不存在,请重试!\033[0m\n') 430 431 def student_int(): 432 ''' 433 学生接口 434 param: 435 return:None 436 ''' 437 438 name = input('请输入用户名:').strip() 439 440 while 1: 441 print('''---- 操作菜单 ---- 442 1.注册 443 2.购买课程 444 3.选择班级 445 4.查看信息 446 5.退出系统''') 447 448 choice = input('请选择操作类型:').strip() 449 450 # 注册 451 if choice == '1': 452 453 # 载入数据文件 454 with open(school_file_path,'br') as f: 455 school_list = pickle.load(f) 456 457 # 选择学校 - 开始 458 length = len(school_list) 459 if length: 460 while 1: 461 # 打印学校列表 462 print('\n---- 学校列表 ----') 463 for i in range(length): 464 print( '%d.%s'%((i+1),school_list[i].name) ) 465 466 num = input('\n请选择学校:').strip() 467 468 if num.isdigit(): 469 index = int(num) - 1 470 471 if 0 <= index < length: 472 school = school_list[index] 473 break 474 475 else: 476 print('\n\033[1;31m您选择的学校不存在,请重试!\033[0m\n') 477 else: 478 print('\n\033[1;31m请输入数字!\033[0m\n') 479 else: 480 print('\n\033[1;31m还未创建学校,请联系管理员处理!\033[0m\n') 481 continue 482 # 选择学校 - 结束 483 484 # 获取用户输入的用户名 并 判断是否有重名 485 486 for student in school_list[index].students: 487 if name == student.name: 488 print('\n\033[1;31m用户名 %s 已在 %s 注册,无需重复注册!\033[0m\n'%(name,school.name)) 489 break 490 else: 491 student = Student(name) 492 student.enroll(school) 493 school_list[index] = school 494 495 # 相关信息写入文件 496 save(school_file_path,school_list) 497 498 print( '\n用户 \033[1;36m%s\033[0m 在 \033[1;36m%s\033[0m 注册成功!\n'%(name,school.name) ) 499 500 # 购买课程 501 elif choice == '2': 502 503 # 载入数据文件 504 with open(school_file_path,'br') as f: 505 school_list = pickle.load(f) 506 507 # 判断是否注册 508 flag = 0 509 for school in school_list: 510 for student in school.students: 511 if name == student.name: 512 stu_obj = student 513 sch_obj = school 514 stu_i = school.students.index(student) 515 sch_i = school_list.index(school) 516 flag = 1 517 break 518 if flag: 519 break 520 else: 521 print('\n\033[1;31m用户名不存在,请先注册!\033[0m\n') 522 continue 523 524 while 1: 525 print('\n---- \033[1;36m%s\033[0m 课程价格----'%school.name) 526 527 length = len(sch_obj.courses) 528 for i in range(length): 529 print('''%d . %s 530 \t课程周期:%d 月\t课程价格:%d 元''' 531 %( (i+1),sch_obj.courses[i].name,sch_obj.courses[i].cycle,sch_obj.courses[i].price) ) 532 533 choice = input('\n请选择要购买的课程([b]:返回):') 534 535 if choice.isdigit(): 536 choice = int(choice) - 1 537 if 0 <= choice < length: 538 course = sch_obj.courses[choice] 539 if course in stu_obj.courses: 540 print('该课程已购买!') 541 continue 542 else: 543 confirm = input( '要支付 %d 元,确定吗?(y/n)'%(course.price) ).strip() 544 if confirm.lower() == 'y': 545 546 # 模拟交易 547 print('连接您的银行账号',end='') 548 for i in range(3): 549 sys.stdout.write('.') 550 time.sleep(0.5) 551 sys.stdout.flush() 552 553 print('\n交易处理中', end='') 554 for i in range(3): 555 sys.stdout.write('.') 556 time.sleep(0.5) 557 sys.stdout.flush() 558 559 print('\n交易完成!') 560 561 stu_obj.pay(course) 562 school.students[stu_i] = stu_obj 563 school_list[sch_i] = school 564 565 # 写入文件 566 save(school_file_path,school_list) 567 568 print('\n您已购买课程 \033[1;36m%s\033[0m ,价格 \033[1;36m%d\033[0m 元,谢谢您的支持!' 569 %(course.name,course.price)) 570 571 else: 572 continue 573 574 else: 575 print('\n\033[1;31m您选择的课程不存在,请重试!\033[0m\n') 576 577 else: 578 if choice == 'b': 579 break 580 else: 581 print('\n\033[1;31m输入错误,请重试!\033[0m\n') 582 583 # 选择班级 584 elif choice == '3': 585 586 # 载入数据文件 587 with open(school_file_path,'br') as f: 588 school_list = pickle.load(f) 589 590 # 判断是否注册 591 flag = 0 592 for school in school_list: 593 for student in school.students: 594 if name == student.name: 595 stu_obj = student 596 sch_obj = school 597 stu_i = school.students.index(student) 598 sch_i = school_list.index(school) 599 flag = 1 600 break 601 if flag: 602 break 603 else: 604 print('\n\033[1;31m用户名不存在,请先注册!\033[0m\n') 605 continue 606 607 # 选择班级 608 609 unselected_classes_set = set(map(lambda x:x.cls,stu_obj.courses)) - set(stu_obj.classes) #未加入班级 610 selected_classes_set = set(map(lambda x: x.cls, stu_obj.courses)) & set(stu_obj.classes) #已加入班级 611 612 if stu_obj.courses: 613 if selected_classes_set: 614 for cls in selected_classes_set: 615 print('您已加入 \033[1;36m%d\033[0m 班!(课程:%s)'%(cls.num,cls.course.name)) 616 617 for cls in unselected_classes_set: 618 619 confirm = input('%s 课程的对应班级为 %d 班,选择该班级吗?(y/n)' % (cls.course.name, cls.num)) 620 621 if confirm.lower() == 'y': 622 stu_obj.select_cls(cls) 623 school_list[sch_i].students[stu_i] = stu_obj 624 625 save(school_file_path, school_list) 626 627 print('\n您已加入 \033[1;36m%d\033[0m 班!(课程:%s)\n'%(cls.num,cls.course.name)) 628 629 else: 630 continue 631 632 print('\n\033[1;36m您已加入所有已购买课程对应的班级!\033[0m\n') 633 634 else: 635 print('\n\033[1;31m请先购买课程!\033[0m\n') 636 637 638 # 显示信息 639 elif choice == '4': 640 # 载入数据文件 641 with open(school_file_path, 'br') as f: 642 school_list = pickle.load(f) 643 644 # 判断是否注册 645 flag = 0 646 for school in school_list: 647 for student in school.students: 648 if name == student.name: 649 stu_obj = student 650 sch_obj = school 651 stu_i = school.students.index(student) 652 sch_i = school_list.index(school) 653 flag = 1 654 break 655 if flag: 656 break 657 else: 658 print('\n\033[1;31m用户名不存在,请先注册!\033[0m\n') 659 continue 660 661 # 显示信息 662 663 # course_names = [] 664 # for course in stu_obj.courses: 665 # course_names.append(course.name) 666 # 667 # cls_nums = [] 668 # for cls in stu_obj.classes: 669 # cls_nums.append(str(cls.num)+'班') 670 671 print('''\n用户名:\033[1;36m%s\033[0m 672 购买课程:\033[1;36m%s \033[0m 673 所在班级:\033[1;36m%s \033[0m''' 674 %(name, 675 ','.join(map(lambda x:x.name,stu_obj.courses)) if stu_obj.courses else '', 676 ','.join(map(lambda x:(str(x.num)+'班'),stu_obj.classes)) if stu_obj.classes else '')) 677 678 input('\n请输入任意键按回车继续...\n') 679 680 elif choice == '5': 681 exit() 682 683 else: 684 if choice == 'b': 685 break 686 else: 687 print('\n\033[1;31m输入错误,请重试!\033[0m\n') 688 689 690 if __name__ == '__main__': 691 pass 692 # admin_int() 693 # teacher_int() 694 # student_int() 695 696 # with open(school_file_path,'rb') as f: 697 # school_list = pickle.load(f) 698 # 699 # for school in school_list: 700 # print('\n ----',school.name,'----') 701 # print('\ncourse:') 702 # for course in school.courses: 703 # print(course.name,course.cycle,course.price) 704 # 705 # print('\nclasses:') 706 # for cls in school.classes: 707 # print(cls.num,cls.course.name) 708 # 709 # for stu in cls.students: 710 # print(stu.name) 711 # 712 # print('\nteachers:') 713 # for teacher in school.teachers: 714 # print(teacher.name,teacher.cls.num,'\nstudents:\t') 715 # 716 # for stu in teacher.cls.students: 717 # print(stu.name) 718 # 719 # print('\nstudents:') 720 # for student in school.students: 721 # print(student.name,student.school.name) 722 # for cou in student.courses: 723 # print(cou.name) 724 # 725 # for cls in student.classes: 726 # print(cls.num)
1 import pickle 2 3 def save(path,acc): 4 with open(path,'wb') as f: 5 pickle.dump(acc,f) 6 7 save('school',[])