python开发之实现选课系统功能
一、需求
- 创建北京、上海 2 所校区
- 创建linux , python , go 3个课程 , linux\py 在北京开, go 在上海开
- 课程包含,周期,价格,通过学校创建课程
- 通过学校创建班级, 班级关联课程
- 创建学员时,关联班级
- 提供三个角色接口
(1)学员视图:可以注册,交学费,选择班级(交学费未实现)
(2)讲师视图:讲师可管理自己的班级,上课时选择班级,查看班级学员列表,修改所管理的学员的成绩(未实现)
(3)管理视图:创建校区,创建讲师,创建班级,创建课程 - 上面的操作产生的数据都通过pickle序列化保存到文件里。
- 主要目的是熟悉Python面向对象编程,清楚类之间的关系
二、程序目录结构
|----bin(可执行目录)
| |----admin.py
| |----initialize.py
| |----student.py
|----config(配置文件目录)
| |----settings.py(配置文件)
|----core(核心代码)
| |----models.py(放各种类)
| |----identifier.py(用于生成唯一ID)
| |----service(主要逻辑)
| | |----admin_service.py
| | |----initialize_service.py
| | |----student_service.py
|----lib(公共的类库)
| |----commons.py(小功能)
|----db(存放对象文件)
| |----admin
| |----classes
| |----course
| |----school
| |----teacher
| |----student
| |----course2teacher2classes
三、需求分析及实现思路
- 每个类下面写一个__init__方法,用来放每个类需要的参数。写一个save方法,直接用pickle.dump将对象保存到文件里,因为调用save需要利用对象来调用:s1.save(),所以save方法可定义为普通方法,里面有self参数。
- 还需要一个get_all_list方法,用pickle.load来展示所有对象,因为不需要通过对象来调用该方法,所以该方法可定义为静态方法,不需要self参数。另外,在类中写个__str__方法,通过调用 get_all_list() 得到的列表,再循环列表打印 obj 时,直接执行__str__方法,返回其返回值。
- 为了规范,每个对象应该有一个标识自己的唯一ID,可用uuid生成,故__init__方法中应该有一条 self.nid = 唯一ID,并且这个唯一ID可以作为保存每个对象的文件的文件名。
- 不同的类之间有可能会产生联系,比如班级类和学生类,每个学生都会有一个班级,在创建学生对象的时候就要指明班级,最好的方法是在学生类下的__init__方法中写一个 self.classesId = classes_id,因为这种情况下classes_id会在班级对象和学生对象中各保存一份,如果将来单纯修改了班级信息,学生对象里保存的班级信息则没有被修改,而ID是不允许修改的,无论怎样修改班级信息,班级ID都不变,只要通过学生对象的班级ID获取班级信息就可以。
- 在Nid类里写一个 get_obj_by_uuid() 方法,该方法里实现了用pickle从文件获取对象,这样通过学生对象获取班级对象时就不用每次都pickle.load文件了,比如:学生 classesId.get_obj_by_uuid().name 就能拿到该学生所在班级。再创建AdminNid类、SchoolNid类并继承Nid类,在每个子类里传入自己的db_path。
- 班级与课程相关,老师也与课程相关。假如王老师同时教Python和Linux两门课,而一班二班上Python,三班上Linux,则王老师需要教一班二班和三班。
- 关系图:
四、代码部分
bin —> admin.py
"""
用于为管理员用户提供相关操作,如:学校、课程、老师等相关操作
"""
from src.service import admin_service
def execute():
admin_service.main()
if __name__ == '__main__':
execute()
bin —> initialize.py
"""
用于初始化管理员账户
"""
from src.service import initialize_service
def execute():
initialize_service.main()
if __name__ == '__main__':
execute()
bin —> student.py
"""
用于为学生提供相关操作,如:学生报名,查看学生信息
"""
from src.service import student_service
def execute():
student_service.main()
if __name__ == '__main__':
execute()
settings.py
import os
BASEDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
ADMIN_DB = os.path.join(BASEDIR, 'db', 'admin')
COURSE_DB = os.path.join(BASEDIR, 'db', 'course')
COU_TEA_CLA_DB = os.path.join(BASEDIR, 'db', 'Course2Teacher2Classes')
CLASSES_DB = os.path.join(BASEDIR, 'db', 'classes')
STUDENT_DB = os.path.join(BASEDIR, 'db', 'student')
TEACHER_DB = os.path.join(BASEDIR, 'db', 'teacher')
SCHOOL_DB = os.path.join(BASEDIR, 'db', 'school')
commons.py
import time
import uuid
import hashlib
# 创建一个唯一ID:
def create_uuid():
return str(uuid.uuid1())
# 得到md5值:
def create_md5():
m = hashlib.md5()
m.update(bytes(str(time.time()), encoding='utf-8'))
return m.hexdigest()
models.py
import os
import time
import pickle
from config import settings
from src import identifier
class BaseModel:
def save(self):
"""
使用pickle将用户对象保存到文件
:return:
"""
nid = str(self.nid)
file_path = os.path.join(self.db_path, nid)
pickle.dump(self, open(file_path, 'wb'))
# obj = Admin('root', 123)
# 将obj写入到db/admin目录
class Admin(BaseModel):
db_path = settings.ADMIN_DB
def __init__(self, username, password):
"""
创建管理员对象
:param username:
:param password:
:return:
"""
# nid