项目需求:
利用规范化目录结构完成一个学生选课系统。
-
**角色:**学生、管理员。
-
功能分析:
- 用户登录之后就可以直接判断用户身份,是学生还是管理员。
- 学生登录之后有以下几个功能:
- 查看所有课程。
- 选择课程。
- 查看所选课程。
- 退出程序。
- 管理员登录之后有以下几个功能:
- 创建课程(需要记录日志)。
- 创建学生账号(需要记录日志)。
- 查看所有课程。
- 查看所有学生。
- 查看所有学生的选课情况。
- 退出程序。
-
课程属性:课程名,价格,周期,老师。
-
学生属性:姓名,所选课程。
-
管理员属性:姓名。
流程图: https://www.processon.com/view/link/5d283960e4b0878e40af9dd8
目录结构:

具体代码:
start.py

import sys
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
sys.path.append(BASE_DIR)
from core import src
from core.src import Course
from core.src import Student
if __name__ == '__main__':
src.main()
settings.py

import os
import logging
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
USERINFO_PATH = os.path.join(BASE_DIR, 'db','user_info')
COURSE_PATH = os.path.join(BASE_DIR, 'db','Course')
STUDENT_PATH = os.path.join(BASE_DIR, 'db','Student')
LOGGING_PATH = os.path.join(BASE_DIR, 'log','admin.log')
SIMPLE_FORMAT = '[%(asctime)s] %(message)s'
LOGGING_DIC = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'simple': {
'format': SIMPLE_FORMAT,
},
},
'filters': {},
'handlers': {
# 打印到终端的日志
'stream': {
'level': 'DEBUG',
'class': 'logging.StreamHandler', # 打印到屏幕
'formatter': 'simple'
},
# 打印到文件的日志,收集info及以上的日志
'file': {
'level': 'DEBUG',
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件
'formatter': 'simple',
'filename': LOGGING_PATH, # 日志文件
'maxBytes': 1024 * 1024 * 5, # 日志大小 5M
'backupCount': 5,
'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了
},
},
'loggers': {
# logging.getLogger(__name__)拿到的logger配置
'': {
'handlers': ['stream', 'file'],
'level': 'DEBUG',
'propagate': True,
},
},
}
src.py

import os
import sys
import pickle
from conf import settings
from lib import common
class Base:
def show_courses(self):
with open(settings.COURSE_PATH, mode="rb") as f:
num = 0
while 1:
try:
num += 1
obj = pickle.load(f)
print(f"{num}: {obj.name} {obj.price} {obj.period}")
except EOFError:
break
def exit(self):
sys.exit(f"\033[0;32m感谢{self.name}使用选课系统!\033[0m")
class Student(Base):
operate_lst = [
("查看可选课程", "show_courses"),
("选择课程", "select_course"),
("查看所选课程", "show_selected_course"),
("退出", "exit")
]
def __init__(self, name):
self.name = name
self.courses = []
def select_course(self):
self.show_courses()
try:
chice_num = input("\033[0;32m请输入要选择的课程序号:\033[0m").strip()
with open(settings.COURSE_PATH, mode="rb") as f:
for i in range(int(chice_num)):
obj = pickle.load(f)
self.courses.append(obj)
print(f"\033[0;32m您已经成功添加了{obj.name}课程\033[0m")
except Exception:
print("输入有误")
def show_selected_course(self):
print(f"\033[0;32m您已报名如下课程\033[0m")
for obj_course in self.courses:
print(f"\033[0;32m课程名:{obj_course.name},课程价格:{obj_course.price} 课程周期:{obj_course.period}\033[0m")
def exit(self):
with open(settings.STUDENT_PATH, mode="rb") as f1,\
open(f"{settings.STUDENT_PATH}_bak", mode="wb") as f2:
while 1:
try:
obj = pickle.load(f1)
pickle.dump(self if obj.name == self.name else obj, f2)
except EOFError:
break
os.remove(settings.STUDENT_PATH)
os.rename(f"{settings.STUDENT_PATH}_bak", settings.STUDENT_PATH)
super().exit()
@classmethod
def get_obj(cls, username):
with open(settings.STUDENT_PATH, mode="rb") as f1:
while 1:
try:
obj = pickle.load(f1)
if username == obj.name:
return obj
except EOFError:
break
class Manager(Base):
operate_lst = [
("创建课程", "create_course"),
("创建学生", "create_student"),
("查看可选课程", "show_courses"),
("查看所有学生", "show_students"),
("查看所有学生选课情况", "show_students_courses"),
("退出", "exit")
]
def __init__(self, name):
self.name = name
def create_course(self):
course = getattr(sys.modules[__name__], "Course")
name, price, period = input("请依次输入课程名,价格以及课程周期,以|分割").strip().split("|")
obj = course(name, price, period)
with open(settings.COURSE_PATH, mode="ab") as f1:
pickle.dump(obj, f1)
logger = common.record_logger()
logger.info(f"成功创建{name}课程")
def create_student(self):
student_username = input("\033[0;32m 请输入学生姓名:\033[0m").strip()
student_password = input("\033[0;32m 请输入学生密码:\033[0m").strip()
student_pwd_md5 = common.hashlib_md5(student_password)
with open(settings.USERINFO_PATH, encoding="utf-8", mode="a") as f1:
f1.write(f"\n{student_username}|{student_pwd_md5}|Student")
with open(settings.STUDENT_PATH, mode="ab") as f:
obj = getattr(sys.modules[__name__], "Student")(student_username)
pickle.dump(obj, f)
logger = common.record_logger()
logger.info(f"您已成功创建学生账号:{student_username},初始密码:{student_password}")
def show_students(self):
with open(settings.STUDENT_PATH, mode="rb") as f1:
while 1:
try:
obj = pickle.load(f1)
print(obj.name)
except EOFError:
break
def show_students_courses(self):
"""查看所有学生选课情况"""
with open(settings.STUDENT_PATH, mode='rb') as f1:
while 1:
try:
obj = pickle.load(f1)
print(f'\033[0;32m学生:{obj.name},所选课程:\
{["%s-%s-%s" %(course.name,course.price,course.period) for course in obj.courses]}\033[0m')
except EOFError:
break
def exit(self):
super().exit()
@classmethod
def get_obj(cls, username):
return Manager(username)
class Course:
def __init__(self, name, price, period):
self.name = name
self.price = price
self.period = period
self.teacher = None
def login():
count = 1
while count < 4:
username = input("请输入用户名: ").strip()
password = input("请输入密码: ").strip()
pwd_md5 = common.hashlib_md5(password)
with open(settings.USERINFO_PATH, encoding="utf-8") as f1:
for line in f1:
if not line.strip():continue
user, pwd, identify = line.strip().split("|")
if user == username and pwd == pwd_md5:
return {"username": user, "identify": identify, "auth": True}
else:
print("用户名或密码错误,请重新输入")
count += 1
return {"username": username, "identify": None, "auth": False}
def main():
print("\033[0;32m欢迎访问选课系统,请先登录\033[0m")
dict_auth = login()
print(f"\033[0;32m登陆成功,欢迎{dict_auth['username']},您的身份是{dict_auth['identify']}\033[0m")
if dict_auth["auth"]:
if hasattr(sys.modules[__name__], dict_auth["identify"]):
cls = getattr(sys.modules[__name__], dict_auth["identify"])
obj = cls.get_obj(dict_auth["username"])
while 1:
for num, option in enumerate(cls.operate_lst, 0):
print(f"{num+1}: {option[0]}")
choice_num = int(input('\033[0;32m 请输入选项:\033[0m').strip())
getattr(obj, cls.operate_lst[choice_num - 1][1])()
else:
print("三次验证失败,系统自动退出")
return False
common.py

import hashlib
import logging.config
from conf.settings import LOGGING_DIC
def hashlib_md5(password):
ret = hashlib.md5()
ret.update(password.encode("utf-8"))
return ret.hexdigest()
def record_logger():
logging.config.dictConfig(LOGGING_DIC)
logger = logging.getLogger()
return logger
来源:https://www.cnblogs.com/duyu123/p/11317854.html
