Welcome to kimi's blog

选课系统

选课系统需求分析

选课系统
  	 角色:学校、学员、课程、讲师
 要求:
    1. 创建北京、上海 2 所学校
    2. 创建linux , python , go 3个课程 , linux\py 在北京开, go 在上海开
    3. 课程包含,课程名称、周期,价格,通过学校创建课程 
    4. 通过学校创建班级, 班级关联课程、讲师5. 创建学员时,选择学校,关联班级
    5. 创建讲师角色时要关联学校, 
    6. 提供三个角色接口  
    	6.1 学员视图:注册、登录、选择课程、 选择学校,查看分数。(交学费、选择班级)  
    	6.2 讲师视图:讲师登录功能、讲师查看课程、讲师选择课程、讲师查看分数、讲师修改分数。
    	6.3 管理视图:注册、登录、创建讲师, 创建班级,创建课程
    7. 上面的操作产生的数据都通过pickle序列化保存到文件里

功能提炼

1.管理员功能
	注册功能
 	登录功能
 	创建学校
 	创建课程
 	创建老师
2.讲师功能
	登录功能
 	选择课程
 	查看课程
 	查看学生分数
	修改学生分数
3.学生功能
	注册功能
 	登录功能
 	选择学校
 	选择课程
 	查看课程分数

项目目的

  在ATM+购物车的基础之上,进一步编写选课系统,要采用面向对象的封装、继承、多态,训练面向对象的思维逻辑

选课系统架构设计

与ATM架构设计的差异
	1.第一层做分层展示
	2.第二层创建moders.py存储所有的类,只有该py文件内的代码有资格调用db_handler

选课系统选用三层架构搭建,图如下

image

详细的架构设计
image

选课系统目录搭建

目录
-start.py
-conf
	-settings.py   一般全大写
-core
	-src.py
-interface
	-admin_interface.py
	-student_interface.py
	-teacher_interface,py
-db
	-moders.py
	-db_handler.py
-log
	-log.log
-lib
	-common.py
-README
-requirements.txt

选课系统详细步骤

功能搭建>>>CSS3项目

启动文件

import os
import sys
base_dir = os.path.dirname(__file__)
sys.path.append(base_dir)

if __name__ == '__main__':
    from core import src
    src.run()

管理员功能搭建

def register():
    pass
def login():
    pass
def create_school():
    pass
def create_course():
    pass
def create_teacher():
    pass
function_dict = {
    '1':register,
    '2':login,
    '3':create_school,
    '4':create_course,
    '5':create_teacher
    '6':delete_teacher,
    '7':delete_student
}

def run():
    while True:
        print("""
        ==================管理员视图======================
        1.管理员注册功能
        2.管理员登录功能
        3.管理员创建学校
        4.管理员创建课程
        5.管理员创建讲师
        6.管理员删除讲师
        7.管理员删除学生
        =================================================
        """)
        choice_num = input('请选择管理员功能编号(q)>>>:').strip()
        if choice_num == 'q':return
        if choice_num in function_dict:
            function_dict.get(choice_num)()
        else:
            print('您选择的功能编号不在执行范围内!!!')def register():
    pass
def login():
    pass
def create_school():
    pass
def create_course():
    pass
def create_teacher():
    pass
function_dict = {
    '1':register,
    '2':login,
    '3':create_school,
    '4':create_course,
    '5':create_teacher
}

def run():
    while True:
        print("""
        1.管理员注册功能
        2.管理员登录功能
        3.管理员创建学校
        4.管理员创建课程
        5.管理员创建讲师
        """)
        choice_num = input('请选择管理员功能编号(q)>>>:').strip()
        if choice_num == 'q':return 
        if choice_num in function_dict:
            function_dict.get(choice_num)()
        else:
            print('您选择的功能编号不在执行范围内!!!')

讲师功能搭建

def login():
    pass
def check_course():
    pass
def choice_course():
    pass
def check_score():
    pass
def update_score():
    pass
function_dict = {
    '1':login,
    '2':check_course,
    '3':choice_course,
    '4':check_score,
    '5':update_score
}

def run():
    while True:
        print("""
        =====================讲师视图====================
        1.讲师登录功能
        2.讲师查看课程
        3.讲师选择课程
        4.讲师查看分数
        5.讲师修改分数
        ================================================
        """)
        choice_num = input('请选择讲师视图的功能编号>>>>:').strip()
        if choice_num == 'q': return
        if choice_num in function_dict:
            function_dict.get(choice_num)()
        else:
            print('您选择的功能编号不在执行范围内!')

学生功能搭建

def register():
    pass
def login():
    pass
def choice_school():
    pass
def choice_course():
    pass
def check_score():
    pass

function_dict = {
    '1':register,
    '2':login,
    '3':choice_school,
    '4':choice_course,
    '5':check_score
}

def run():
    while True:
        print("""
        ===================学生视图==================
        1.学生注册功能
        2.学生登录功能
        3.学生选择学校
        4.学生选择课程
        5.学生查看分数
        ==============================================
        """)
        choice_num = input('请选择学生视图的功能编号>>>>:').strip()
        if choice_num == 'q':return
        if choice_num in function_dict:
            function_dict.get(choice_num)()
        else:
            print('您选择的功能编号不在执行范围内!')

核心功能分析

关于管理员视图、学生视图、讲师视图是分开的模块,我们登录之后想要记录当下的登录状态,首先第一个在各自的模块用is_login= {'username':''}来记录,登录成功之后修改登录的状态is_login['username'] = admin_name,调用装饰器来校验用户是否登录,涉及到我们是三个模块,需要传参数,那么就用到有参装饰器,通过优化我们可以优化如下

1.装饰器
def login_auth(user_type):
    def outer(func_name):
        def inner(*args,**kwargs):
            # from core import admin_view, teacher_view, student_view
            # MODERS_DICT = {
            #     'admin': admin_view,
            #     'teacher': teacher_view,
            #     'student': student_view

            if user_type in settings.MODERS_DICT:
                if settings.MODERS_DICT.get(user_type).is_login.get('username'):
                    res = func_name(*args, **kwargs)
                    return res
                else:
                    print('您尚未登录,请先登录!!!')
                    settings.MODERS_DICT.get(user_type).login()

            # if user_type == 'admin':
            #     if admin_view.is_login.get('username'):
            #         res = func_name(*args,**kwargs)
            #         return res
            #     else:
            #         print('您尚未登录,请先登录!!!')
            #         admin_view.login()
            # elif user_type == 'teacher':
            #     if teacher_view.is_login.get('username'):
            #         res = func_name(*args,**kwargs)
            #         return res
            #     else:
            #         print('您尚未登录,请先登录!!!')
            #         teacher_view.login()
            # elif user_type == 'student':
            #     if student_view.is_login.get('username'):
            #         res = func_name(*args,**kwargs)
            #         return res
            #     else:
            #         print('您尚未登录,请先登录!!!')
            #         student_view.login()

        return inner
    return outer
2.数据的保存采用pickle模块,能将python的对象类型序列化存储到文件里,而对象中存储了对象独有的数据。
3.每种对象数据都有存储功能,我们可以让它继承父类中的存储功能,使用类名和对象进行区别,做到‘分类’存储
4.models.Admin 数据层的admin类,使用了封装的思想,先将pwd隐藏起来,让用户不能读取,再开放接口进行校验。这个数据属于敏感数据,所以就使用了封装后开放接口的做法,来避免这个数据被滥用。
如下
class Admin(Bases):
    def __init__(self, name, pwd):
        self.name = name
        self.__pwd = pwd
        self.save()

  
5.关于课程管理老师或者学生的做法
学生添加课程的接口层
def choice_course_interface(temp_course_list,student_name):
    student_obj = moders.Student.select_obj(student_name)
    # 去重
    old_course_list = set(student_obj.course_list)
    new_course_list = set(temp_course_list)
    course_list = list (old_course_list | new_course_list)
    # 保存
    student_obj.course_list = course_list
    student_obj.save_obj()
    # 学生成绩初始化
    student_obj.course_score_dict = {name:'暂无成绩' for name in student_obj.course_list}
    student_obj.save_obj()

    # 课程绑定学生
    for course_name in student_obj.course_list:
        course_obj = moders.Course.select_obj(course_name)
        course_obj.student_name_list.append(student_name)
        course_obj.save_obj()

    return True,f'学生{student_name}添加了课程后为{course_list}'

管理员视图

管理员注册功能

第一层 视图数据展示层
	1.获取用户名和密码
	2.校验两次密码
	3.调用管理员接口(传用户名和密码)
第二层 接口逻辑层
	1.判断管理员是否已经存在
	2.密码加密(创建一个公共的加密方法,放在了common,方便以后调用)
	3.创建管理员对象并保存
第三层 数据处理层
	1.在models模块定义一个类Admin,编辑管理员独有的功能
	2.接着定义一个父类,里面调用存放数据保存和查询的方法,因为继承封装之后,很多类都可继承直接使用父类的方法
	3.在db_handler模块中,定义对象保存(save)和对象查询(select)的方法

管理员登录功能

第一层 视图数据展示层
	1.获取用户名和密码
	2.直接调用接口层
第二层 接口逻辑层
	1.调用第三层获取管理员对象,判读是否存在
	2.调用加密函数,判断密码是否正确
	3.登录成功
第三层 数据处理层
	3.查询管理员对象
管理员登录之后可以直接操作创建学校、课程和讲师
1.管理员登录之后就保存状态>>在登录成功之后修改is_login字典中的用户状态,校验用户是否登录,引入一个校验用户登录的装饰器,考虑到学生和讲师视图都用到,视图不一样,用到有参装饰器(建议模块名不同,用自己存储,for循环调用)

2.我们在父类Bases定义可以直接调用创建学校、课程和讲师的方法
	 def create_school(self,school_name,school_address):
        School(school_name,school_address)
        
    def create_cource(self,cource_name,cource_price,cour_period):
        Cource(cource_name,cource_price,cour_period)

    def create_teacher(self,teacher_name,):
        Teacher(teacher_name)

管理员创建学校

第一层 视图数据展示层
	1.获取学校名字和地址
	2.传学校名字和地址给第二层接口
第二层 接口逻辑层
	1.创建一个学校类
	2.校验学校是否已经创建
	3.获取管理员对象,通过对象点方式去保存admin_obj.create_school(school_name,school_address)
	
第三层 数据处理层

管理员创建课程

"""课程是跟学校绑定的,先获取学校,再获取课程 >>>防止先选择课程,先在获取所有学校中做一个判断,如果没有,则创建一个类的路径"""
第一层 视图数据展示层
	1.调用第二层接口获取所有的学校列表
	2.循环学校给管理员选择(小判断),获取学校名字
	3.获取创建的课程名称,价格,信息,传给第二层接口
第二层 接口逻辑层
	1.创建一个课程类
	2.调用moders获取所有学校的列表(一个方法)
	3.调用moders,判断学校是否创建,没有则无法课程
	4.判通过学校对象判断学校是否已经创建该课程
	5.管理员创建课程  admin_obj.create_cource(cource_name,cource_price,cource_period)
	6.学校要和课程绑定,后保存 school_obj.save_obj()
第三层 数据处理层

管理员创建讲师

第一层 视图数据展示层
	1.获取讲师用户名(讲师密码是默认的)
	2.传讲师姓名给老师接口
第二层 接口逻辑层
	1.先创建一个老师类
	2.校验老师名字是否存在
	3.管理员创建老师 admin_obj.create_teacher(teacher_name)
第三层 数据处理层

讲师视图

讲师登录功能

第一层 视图数据展示层
	1.获取学生用户名和密码
	2.直接调用接口层
第二层 接口逻辑层
	1.调用第三层获取管理员对象,判读是否存在
	2.调用加密函数,判断密码是否正确
	3.登录成功,保存登录状态
第三层 数据处理层

讲师查看课程

 """1.获取所有的学校,查看学校的课程"""
第一层 视图数据展示层
	1.调用第二层获取学校的学校列表
	2.循环学校列表供学校选择,获取目标学校
	3.传target_school_name和老师名字,调用第二层接口保存
	4.拿到学校课程,打印给老师查看
第二层 接口逻辑层
	 1.获取学校列表,返回学校列表
	 2.查看学校对象,判断学校是否添加课程
	 3.返回学校课程给第一层
第三层 数据处理层

讲师选择课程

"""学校>>>>课程"""
第一层 视图数据展示层
	1.调用第二层接口,查看讲师可供选择的所有课程列表
	2.循环课程列表供老师选择,获取目标课程
	3.定义一个临时列表添加目前选的课程列表,判断不能选择重复的
	4.老师退出就保存临时列表,调用第二层接口,传老师姓名、临时字典
第二层 接口逻辑层
	1.通过moders查看所有的课程列表返回给第一层
	2.通过获取讲师对象,新旧课程列表去重后并起来
	3.添加老师课程列表
	4.课程绑定老师,课程列表里面老师列表依次添加老师名字,并保存
第三层 数据处理层】

讲师查看分数

""" 2.获取自己教授课程下的学生成绩"""
第一层 视图数据展示层
	1.掉用第二层接口,获取讲师授课下的课程列表
	2.循环课程列表供老师选择,获取选择的课程
	3.通过调用第二层接口,获取选择这个课程的学生列表
	4.循环学生列表给老师想要修改的学生名字,获取目标学生
	5.通过调用第二接口,通过学生对象,获取目标学生的成绩字典,返回给第一层
	6.美化课程
第二层 接口逻辑层
	1.通过老师对象,返回teacher_obj.teach_cource_list
	2.通过课程对象,获取课程下的学生列表,返回给第一层
	3.通过学生对象,返回给学生成绩的字典
	
第三层 数据处理层

讲师修改分数

""" 2.获取自己教授课程下的学生成绩"""
第一层 视图数据展示层
	1.掉用第二层接口,获取讲师授课下的课程列表
	2.循环课程列表供老师选择,获取选择的课程
	3.通过调用第二层接口,获取选择这个课程的学生列表
	4.循环学生列表给老师想要修改的学生名字,获取目标学生
	5.通过调用第二接口,通过学生对象,获取目标学生的成绩字典,返回给第一层
	6.获取更改后的成绩
	7.传数据给第二层,通过字典的键去更改字典成绩,保存数据
第二层 接口逻辑层
	1.通过老师对象,返回teacher_obj.teach_cource_list
	2.通过课程对象,获取课程下的学生列表,返回给第一层
	3.通过学生对象,返回给学生成绩的字典
	

学生视图

学生注册功能

第一层 视图数据展示层
	1.获取学生名字和密码
	2.判断两次密码是否一致
	3.将名字和密码传给接口层
第二层 接口逻辑层
	1.获取学生对象,判断用户是否已经注册
	2.加密比对
	3.传给第三层models.Student(student_name,hash_pwd)
第三层 数据处理层

学生登录功能

第一层 视图数据展示层
	1.获取学生名字和密码
	2.传学生名字和密码,调用第二层接口比对
第二层 接口逻辑层
	1.获取学生对象,判断学生对象是否存在
	2.密码加密,比对
	3.登录成功>>>>记录学生登录状态
第三层 数据处理层

学生选择学校

第一层 视图数据展示层
	1.调用第二层获取学校的学校列表
	2.循环学校列表供学校选择,获取目标学校
	3.调用第二层接口保存
第二层 接口逻辑层
	1.调用moders获取学校列表
	2.获取学生对象,判断学生是否选择过该学校
	3.学生对象添加学校,进行保存
第三层 数据处理层

学生选择课程

 """1.先获取学生的学校 然后获取该学校下的课程
    2.直接展示所 有的课程供学生选择"""
第一层 视图数据展示层
	1.调用第二层获取学生的学校,直接返回学校的课程列表
	2.循环打印课程列表供学生选择,获取目标课程
	3.建立临时列表保存选择的课程,判断是否选择过课程
	4.添加到临时列表,用户退出保存临时列表
	5.调用第二层保存临时列表
第二层 接口逻辑层
	1.调用moders获取学校的课程列表
	2.获取学生对象,判断学生是否已经选择过该课程
	3.学生的旧列表去重,获取的新列表去重,新旧列表重合
	4.学生成绩初始化后保存,如果再次添加就做判断添加的课程是否在列表里
	5.课程绑定学生,保存
第三层 数据处理层

学生查看分数

第一层 视图数据展示层
	1.调用第二层,获取学生的成绩字典
	2.美化课程展示
第二层 接口逻辑层
	1.获取学生对象,获取学生字典,判断是否添加过课程
第三层 数据处理层
posted @ 2022-11-09 18:34  魔女宅急便  阅读(62)  评论(0)    收藏  举报
Title