學生選課系統項目開發 1.項目需求 1. 創建北京、上海 2 所學校 2. 創建linux , python , go 3個課程 , linux\py 在北京開, go 在上海開 3. 課程包含,周期,價格,通過學校創建課程 4. 通過學校創建班級, 班級關聯課程、講師 5. 創建學員時,選擇學校, ...
學生選課系統項目開發
1.項目需求
1. 創建北京、上海 2 所學校
2. 創建linux , python , go 3個課程 , linux\py 在北京開, go 在上海開
3. 課程包含,周期,價格,通過學校創建課程
4. 通過學校創建班級, 班級關聯課程、講師
5. 創建學員時,選擇學校,關聯班級
6. 創建講師角色時要關聯學校,
7. 提供兩個角色介面,一個管理介面
2.項目分析
各部分需要完成的任務
管理員視圖:
1. 註冊
2. 登錄
3. 創建講師
4. 創建學校
5. 創建學生
講師視圖:
1. 登錄
2. 講課
3. 查看學生成績
學生視圖:
1. 註冊
2. 登錄
3. 選擇課程
4. 查看分數
分析:
- 和上一個atm相似.本項目也是採用用戶層. 介面層. 資料庫層三層架構
- 代碼中要用到面向對象編程寫. 具體的代碼邏輯如下圖
文件夾結構預覽:
3.代碼部分
本文篇幅較長. 可使用導航欄點擊標題部分查看:
bin文件夾
start.py
# -*- encoding:utf-8 -*- # @time: 2022/7/22 10:20 # @author: Maxs_hu import os import sys BASE_PATH = os.path.dirname(os.path.dirname(__file__)) sys.path.append(BASE_PATH) # 直接將項目根目錄加上. 後面全部可以直接調用. 一勞永逸 from core.src import run if __name__ == '__main__': run()
conf文件夾
settings.py
# -*- encoding:utf-8 -*- # @time: 2022/7/22 10:36 # @author: Maxs_hu import os BASE_PATH = os.path.dirname(os.path.dirname(__file__)) DB_PATH = os.path.join(BASE_PATH, 'db') SCHOOL_DB_PATH = os.path.join(DB_PATH, 'school')
core文件夾
admin.py
# -*- encoding:utf-8 -*- # @time: 2022/7/22 10:37 # @author: Maxs_hu from interface import common_interface, admin_interface from lib import common # 設置用戶登錄狀態 admin_status = { "name": None } def admin_register(): while True: print('管理員註冊') username = input('請輸入用戶名>>>').strip() password = input('請輸入密碼>>>').strip() if password: flag, msg = admin_interface.admin_register_interface(username, password) # 調介面 if not flag: print(msg) else: print(msg) break def admin_login(): while True: print('管理員登錄') username = input('請輸入用戶名>>>').strip() password = input('請輸入密碼>>>') if admin_status['name'] == username: print('已登錄完成. 無需重覆登錄') break if password: flag, msg = common_interface.login_interface(username, password, 'admin') # 調介面 if not flag: print(msg) else: admin_status["name"] = username print(msg) break @common.auth_login(user_type='admin') def create_teacher(): print('創建講師') teacher_name = input('請輸入老師名稱>>>').strip() teacher_password = input('請設置老師密碼>>>').strip() if teacher_name: flag, msg = admin_interface.create_teacher_interface(admin_status['name'], teacher_name, teacher_password) if flag: print(msg) else: print(msg) else: print('老師名不能為空') @common.auth_login(user_type='admin') def create_school(): print('創建學校') school = input('請輸入學校名稱>>>').strip() addr = input('請輸入學校地址>>>').strip() if school: flag, msg = admin_interface.create_school_interface(admin_status['name'], school, addr) if flag: print(msg) else: print(msg) else: print('學校名稱不能為空') @common.auth_login(user_type='admin') def create_course(): while True: print('創建課程') # 先查看學校. 再創建課程. 最後在學校中添加課程 school_list = common_interface.check_school_interface() for i, school in enumerate(school_list): print("%s: %s" % (i+1, school)) choice = input('請輸入需要選擇的校區>>>').strip() course_name = input('請輸入需要添加的課程>>>').strip() course_fee = input('請輸入課程費用>>>').strip() if choice.isdigit(): choice = int(choice) if 0 < choice <= len(school_list): flag, msg = admin_interface.create_course_interface(admin_status['name'], course_name, course_fee, school_list[choice-1]) if flag: print(msg) break else: print(msg) else: print('請輸入有效數字') else: print('請輸入數字') func_dic = { '1': admin_register, '2': admin_login, '3': create_teacher, '4': create_school, '5': create_course, } def admin_view(): while True: print(""" 1. 註冊 2. 登錄 3. 創建講師 4. 創建學校 5. 創建課程 """) choice = input('請輸入的業務序號(q退出)>>>').strip() if choice not in func_dic: print('沒有業務信息') break if choice == "q": break func_dic[choice]()
src.py
# -*- encoding:utf-8 -*- # @time: 2022/7/22 10:37 # @author: Maxs_hu from core import admin, student, teacher identify_dic = { "1": admin.admin_view, "2": teacher.teacher_view, "3": student.student_view, } def run(): while 1: print(""" >>>歡迎進入選課系統<<< 1. 管理員 2. 講師 3. 學生 """) choice = input('請輸入身份(q退出)>>>').strip() if choice == 'q': print('選課系統已關閉') break if not choice in identify_dic: print('無相關身份') break identify_dic[choice]() # 直接加括弧調用
student.py
# -*- encoding:utf-8 -*- # @time: 2022/7/22 10:37 # @author: Maxs_hu from interface import student_interface, common_interface from lib import common # 用戶登錄狀態 student_status = { 'name': None } def student_register(): print('學生註冊') while True: username = input('請輸入用戶名>>>').strip() password = input('請輸入密碼>>>').strip() if password: flag, msg = student_interface.student_register_interface(username, password) if flag: print(msg) break else: print(msg) else: print('用戶名或密碼不能為空') def student_login(): print('學生登錄') while True: username = input('請輸入用戶名>>>').strip() password = input('請輸入密碼>>>').strip() if student_status['name'] == username: print('已登錄完成. 無需重覆登錄') break if password: flag, msg = common_interface.login_interface(username, password, 'student') if flag: student_status['name'] = username print(msg) break else: print(msg) else: print('用戶名和密碼不能為空') @common.auth_login(user_type='student') def choose_school(): while True: print('選擇學校') school_list = student_interface.check_all_school_interface() for i, school in enumerate(school_list): print('%s: %s' % (i+1, school)) choice = input('請輸入你想選擇的學校>>>').strip() if choice.isdigit(): choice = int(choice) if 0 < choice <= len(school_list): flag, msg = student_interface.choose_school_interface(student_status['name'], school_list[choice-1]) print(msg) break else: print('請輸入有效數字') else: print('請輸入數字') @common.auth_login(user_type='student') def choose_course(): while True: print('選擇課程') # 先查看可以選擇的課程. 在進行選課 flag, msg = student_interface.check_avaliable_course_interface(student_status['name']) if flag: for i, course in enumerate(msg): print('%s: %s' % (i+1, course)) choice = input('請輸入你想選擇的課程>>>').strip() if choice.isdigit(): choice = int(choice) if 0 < choice <= len(msg): flag, msg = student_interface.choose_course_interface(student_status['name'], msg[choice-1]) if flag: print(msg) break else: print(msg) else: print('請輸入有效數字') else: print('請輸入數字') else: print('沒有可以選擇的課程') break @common.auth_login(user_type='student') def check_score(): print('查看成績') flag, msg = student_interface.check_score_interface(student_status['name']) print(msg) func_dic = { '1': student_register, '2': student_login, '3': choose_school, '4': choose_course, '5': check_score, } def student_view(): while True: print(''' 1 註冊 2 登錄 3 選擇學校 4 選擇課程 5 查看成績 ''') choice = input('請選擇辦理的業務>>>').strip() if choice not in func_dic: print('無此業務') break func_dic[choice]()
teacher.py
# -*- encoding:utf-8 -*- # @time: 2022/7/22 10:37 # @author: Maxs_hu from interface import teacher_interface, common_interface from lib import common # 用戶狀態 teacher_status = { 'name': None } def teacher_register(): print('講師註冊') while True: username = input('請輸入用戶名>>>').strip() password = input('請輸入密碼>>>').strip() if password: flag, msg = teacher_interface.teacher_register_interface(username, password) if flag: print(msg) break else: print(msg) else: print('用戶名和密碼不能為空') def teacher_login(): print('講師登錄') while True: username = input('請輸入用戶名>>>').strip() password = input('請輸入密碼>>>').strip() if teacher_status['name'] == username: print('已登錄完成. 無需重覆登錄') break if password: flag, msg = common_interface.login_interface(username, password, 'teacher') if flag: teacher_status['name'] = username print(msg) break else: print(msg) else: print('用戶名或密碼不能為空') @common.auth_login(user_type='teacher') def choose_course(): while True: print('選擇課程') # 先查看所有的課程. 在添加課程到teacher類中 course_list = teacher_interface.choose_course_interface() for i, course in enumerate(course_list): print('%s: %s' % (i+1, course)) choice = input('請輸入你想選擇的課程>>>').strip() if choice.isdigit(): choice = int(choice) if 0 < choice <= len(course_list): flag, msg = teacher_interface.add_course_interface(teacher_status['name'], course_list[choice-1]) if flag: print(msg) break else: print(msg) else: print('請輸入有效數字') else: print('請輸入數字') @common.auth_login(user_type='teacher') def check_course(): while True: print('查看課程') course_list = teacher_interface.check_course_interface(teacher_status['name']) if course_list: for course in course_list: print(course) break else: print("請先選擇課程") @common.auth_login(user_type='teacher') def check_student(): while True: print('查看學生') # 先查看課程. 再查看課程對應的學生 course_list = teacher_interface.check_course_interface(teacher_status['name']) for i, course in enumerate(course_list): print('%s: %s' % (i+1, course)) choice = input('請選擇想要查看的課程.課程對應的學生會被返回>>>').strip() if choice.isdigit(): choice = int(choice) if 0 < choice <= len(course_list): student_list = teacher_interface.check_student_interface(course_list[choice-1]) if student_list: for student in student_list: print(student) break else: print('暫時沒有學生') break else: print('請輸入有效的數字') else: print('請輸入數字') @common.auth_login(user_type='teacher') def modify_score(): while True: print('修改學生成績') # 先查看課程. 再查看課程對應的學生. 在對學生進行打分 course_list = teacher_interface.check_course_interface(teacher_status['name']) for i, course in enumerate(course_list): print('%s: %s' % (i + 1, course)) choice = input('請選擇想要查看的課程.課程對應的學生會被返回>>>').strip() if choice.isdigit(): choice = int(choice) if 0 < choice <= len(course_list): course = course_list[choice-1] student_list = teacher_interface.check_student_interface(course) if student_list: for i, student in enumerate(student_list): print('%s: %s' % (i + 1, student)) choice = input('請輸入學生名稱並對其進行打分>>>').strip() score = int(input('請輸入要打的分數>>>').strip()) if choice.isdigit(): choice = int(choice) if 0 < choice <= len(student_list): flag, msg = teacher_interface.modify_score_interface(student_list[choice-1], course, score, ) print(msg) break else: print('請輸入有效數字') else: print('請輸入數字') else: print('暫時沒有學生') else: print('請輸入有效的數字') else: print('請輸入數字') func_dic = { '1': teacher_register, '2': teacher_login, '3': choose_course, '4': check_course, '5': check_student, '6': modify_score } def teacher_view(): while True: print(""" 1. 註冊 2. 登錄 3. 選擇課程 4. 查看課程 5. 查看學生 6. 修改學生成績 """) choice = input('請輸入想要辦理的業務>>>').strip() if choice not in func_dic: print('無此業務') break func_dic[choice]()
db文件夾
db_handler.py
# -*- encoding:utf-8 -*- # @time: 2022/7/22 13:44 # @author: Maxs_hu from conf import settings import os import pickle def save(obj): db_dir = settings.DB_PATH db_path = os.path.join(db_dir, obj.__class__.__name__.lower()) # /admin if not os.path.exists(db_path): os.makedirs(db_path) # 創建文件夾 detail_path = os.path.join(db_path, obj.name) with open(detail_path, 'wb') as f: pickle.dump(obj, f) # 直接將對象寫到pickle中 f.flush() # 刷入硬碟 def select(name, type_dir): db_dir = settings.DB_PATH db_path = os.path.join(db_dir, type_dir) if not os.path.exists(db_path): os.makedirs(db_path) # 創建文件夾 detail_path = os.path.join(db_path, name) if os.path.exists(detail_path): # 判斷文件夾是否存在 with open(detail_path, 'rb') as f: return pickle.load(f) # 將查詢到的信息返回 else: return None
moudle.py
# -*- encoding:utf-8 -*- # @time: 2022/7/22 13:44 # @author: Maxs_hu from db import db_handler class BaseClass: def save(self): db_handler.save(self) @classmethod def get_obj_by_name(cls, name): return db_handler.select(name, cls.__name__.lower()) # 直接將類的名字進行傳參 class Admin(BaseClass): def __init__(self, name, password): self.name = name self.password = password self.save() # 這樣將Admin實例化可以直接調用保存功能 # 管理員功能設置 def create_teacher(self, name, password): # 直接初始化一個類即可 Teacher(name, password) def create_school(self, name, addr): School(name, addr) def create_course(self, name, fee): Course(name, fee) class Teacher(BaseClass): def __init__(self, name, password): self.name = name self.password = password self.course_list = [] self.save() def add_course(self, name): self.course_list.append(name) self.save() class Student(BaseClass): def __init__(self, name, password): self.name = name self.password = password self.school = None self.score = {} self.course_list = [] self.save() def choose_school(self, school): self.school = school self.save() def get_school(self): return self.school def choose_course(self, course): self.course_list.append(course) self.score[course] = 0 # 初始化為0分 self.save() def modify_score(self): self.save() class School(BaseClass): def __init__(self, name, addr): self.name = name self.addr = addr self.course_list = [] self.save() def add_course(self, name): # 課程和學校綁定 self.course_list.append(name) self.save() class Course(BaseClass): def __init__(self, name, fee): self.name = name self.fee = fee self.student_list = [] self.save() def add_student(self, name): self.student_list.append(name) self.save() # 這裡存在一個報錯案例: 原因在於我程式沒編寫完成之前做了測試. 後期填寫的屬性都沒有在已保存的類型中. 導致報錯no attribute
interface文件夾
admin_interface.py
# -*- encoding:utf-8 -*- # @time: 2022/7/22 14:21 # @author: Maxs_hu from db import moudle def admin_register_interface(username, password): admin_obj = moudle.Admin.get_obj_by_name(username) if admin_obj: return False, '管理員已註冊' else: moudle.Admin(username, password) # 直接實例化__init__觸發save() return True, f'{username}已註冊' def create_teacher_interface(username, teacher_name, teacher_password): teacher_obj = moudle.Teacher.get_obj_by_name(teacher_name) # 查看老師是否存在 if teacher_obj: return False, '老師已存在' else: obj = moudle.Admin.get_obj_by_name(username) obj.create_teacher(teacher_name, teacher_password) # 通過對象調用綁定對象 return True, f'{teacher_name}創建完成' def create_school_interface(username, school_name, school_addr): school_obj = moudle.School.get_obj_by_name(school_name) # 判斷學校是否存在 if school_obj: return False, '學校已經存在' else: obj = moudle.Admin.get_obj_by_name(username) obj.create_school(school_name, school_addr) return True, f'{school_name}創建完成' def create_course_interface(username, course_name, course_fee, school): course_obj = moudle.Course.get_obj_by_name(course_name) if course_obj: return False, '課程已存在' else: # 先創建課程 obj = moudle.Admin.get_obj_by_name(username) obj.create_course(course_name, course_fee) # 將課程和學校綁定 school_obj = moudle.School.get_obj_by_name(school) school_obj.add_course(course_name) return True, f'{course_name}創建完成'
student_interface.py
# -*- encoding:utf-8 -*- # @time: 2022/7/22 17:11 # @author: Maxs_hu from db import moudle import os from conf import settings def student_register_interface(username, password): student_obj = moudle.Student.get_obj_by_name(username) if student_obj: return False, '該用戶已存在' else: moudle.Student(username, password) return True, f'{username}已註冊' def check_all_school_interface(): db_path = settings.DB_PATH school_path = os.path.join(db_path, 'school') if os.path.exists(school_path): return os.listdir(school_path) else: return '請聯繫管理員創建學校' def choose_school_interface(username, school): student_obj = moudle.Student.get_obj_by_name(username) student_obj.choose_school(school) return True, '學校選擇完畢' def check_score_interface(username): obj = moudle.Student.get_obj_by_name(username) score = obj.score if score: return True, score else: return False, '請聯繫老師進行打分' def check_avaliable_course_interface(username): student_obj = moudle.Student.get_obj_by_name(username) school = student_obj.get_school() if school: school_obj = moudle.School.get_obj_by_name(school) return True, school_obj.course_list else: return False, '請先選擇學校' def choose_course_interface(username, course): obj = moudle.Student.get_obj_by_name(username) if course in obj.course_list: return False, '您已選過該課程' obj.choose_course(course) course_obj = moudle.Course.get_obj_by_name(course) course_obj.add_student(username) return True, '選課成功'
teacher_interface.py
# -*- encoding:utf-8 -*- # @time: 2022/7/22 17:11 # @author: Maxs_hu from db import moudle from conf import settings import os def teacher_register_interface(username, password): if moudle.Teacher.get_obj_by_name(username): return False, '用戶已存在' else: moudle.Teacher(username, password) return True, f'{username}用戶已註冊' def choose_course_interface(): path = settings.DB_PATH course_path = os.path.join(path, 'course') if os.path.exists(course_path): course_list = os.listdir(course_path) return course_list else: return '請聯繫管理員創建課程' def add_course_interface(username, course): teacher_obj = moudle.Teacher.get_obj_by_name(username) if course in teacher_obj.course_list: return False, '該課程已經選過了' else: teacher_obj.add_course(course) return True, f'{course}選擇完成' def check_course_interface(name): teacher_obj = moudle.Teacher.get_obj_by_name(name) return teacher_obj.course_list def check_student_interface(course): obj = moudle.Course.get_obj_by_name(course) return obj.student_list def modify_score_interface(name, course, score): student_obj = moudle.Student.get_obj_by_name(name) student_obj.score[course] = score student_obj.modify_score() return True, '打分完成'
common_interface.py
# -*- encoding:utf-8 -*- # @time: 2022/7/22 21:23 # @author: Maxs_hu from db import moudle import os from conf import settings def login_interface(name, password, user_type): global obj if user_type == "admin": obj = moudle.Admin.get_obj_by_name(name) # 直接拿到admin的對象. 方便後面調用 elif user_type == "teacher": obj = moudle.Teacher.get_obj_by_name(name) elif user_type == "student": obj = moudle.Student.get_obj_by_name(name) else: return False, '沒有這個用戶類型' if obj: if obj.password == password: return True, '%s登錄成功' % name else: return False, '密碼錯誤' else: return False, '用戶不存在' def check_school_interface(): school_path = settings.SCHOOL_DB_PATH if os.path.exists(school_path): school_list = os.listdir(school_path) return school_list else: return None
lib文件夾
common.py
# -*- encoding:utf-8 -*- # @time: 2022/7/22 10:36 # @author: Maxs_hu # 寫一個加參裝飾器 def auth_login(user_type): from core import admin, teacher, student # 在局部變數內導入. 每次需要時才使用. 防止交叉調用 def auth(func): def wrapper(*args, **kwargs): if user_type == 'admin': if not admin.admin_status['name']: admin.admin_login() # 直接調用登錄介面進行登錄 else: res = func(*args, **kwargs) return res elif user_type == 'student': if not student.student_status['name']: student.student_login() else: return func(*args, **kwargs) elif user_type == 'teacher': if not teacher.teacher_status['name']: teacher.teacher_login() else: return func(*args, **kwargs) else: raise TypeError('沒有此類型') return wrapper return auth
4.運行效果及總結
以上是部分運行截圖. 在代碼完成過後還發生過一些錯誤:
- 最後測試的時候一直報類的no attribute. 找了半天發現原因是在編程中途存的數據. 在那個類中還沒有存放那個屬性. 所以一定要註意在程式開發中 -> 之前的測試數據可能跟後期的不匹配
- 程式健壯性問題: 一個程式可能有很多中報錯的類型. 這就需要在編程的時候足夠細心. 儘量將報錯方式都想到. 實在不行可以使用try...except捕獲異常
- 變數及程式命名問題: 如果命名出現相同可能會導致程式之間發生交叉調用. 我們要儘量避免這種命名相同. 讓每一個變數都有自己的獨特的含義
- 數據儲存問題: 每一次調用到資料庫中的類去改變數據之後不能僅僅只是錶面上改變. 而要去調永db_handler中的save方法. 將數據保存到本地地址裡面. 這樣後面在使用的時候才會有記錄
- 最後一個就是程式之間的調用一定要邏輯清晰. 稍有不慎可能就調錯了類或者傳錯了名字. 這就需要程式命名可讀性高. 編碼的時候保持細心. 思路清晰.
本文來自博客園,作者:{Max},僅供學習和參考