需求
角色:学校、学员、课程、讲师
要求:
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',[])
来源:https://www.cnblogs.com/jailly/p/6963255.html
