[Python学习日记-74] 面向对象实战2——选课系统

[Python学习日记-74] 面向对象实战2——选课系统

简介

开发要求

实现:选课系统

简介

        在前面的《年会答题系统》当中我们介绍了面向对象软件开发的一些流程,当然这一流程只是涵括了大部分的,目前在业界也没有一个统一的标准,每个企业自己都有一套软件开发流程,但是在学习阶段对于借鉴一些标准化的开发流程还是非常有意义的。本篇将会来做一个选课系统,同样也会参照前面《年会答题系统》的模式来进行开发。

开发要求

角色:学校、学员、课程、讲师、管理员


要求:
1.管理员创建北京、上海2所学校
2.创建 linux、python、go 3个课程,linux 和 py 在北京开展授课,go 在上海开展
3.课程包含:周期和价格,通过学校创建课程
4.创建讲师
5.创建学员时,选择学校,并关联课程
6.提供三个角色接口
    6.1 学员视图:可以注册、交学费(可选)、选择课程(等同于选择班级)、去上课
    6.2 讲师视图:讲师可管理自己的课程,上课时选择课程,还可以查看班级学员列表,修改所管理的学员的成绩
    6.3 管理视图:创建讲师、创建学校、创建课程
7.上面的操作产生的数据都通过 pickle 序列化保存到文件里

实现:选课系统

一、需求分析

1、用例名称

        选课系统

2、场景

        when:课程上线后,任意时间使用

        where:某学校

        who:学生、老师、管理员

3、用例描述

        - 管理试图

                1.管理员注册登录

                2.管理员创建学校:北京和上海两个校区

                3.管理员创建课程(先选择校区):python 周末班1期,go 脱产班2期,linux 架构班3期

                4.创建讲师:Jove、Kerry、Lucy、Amy

        - 讲师视图

                1.讲师登录

                2.讲师查看教授课程

                3.讲师选择教授课程

                4.讲师查看课程下的学员

                5.修改分数:讲师为 python 周末班1期第7次课的所有学生批改作业,为每个学生打上分数

        - 学员视图

                1.学员注册登录:波多野结衣,花野真衣,川岛芳子

                2.学员选择校区

                3.学员选择课程(先选择校区,再选择校区中的某一门课程,即学生选择课程,课程也选择学生)

                4.学员上课,产生上课记录

                5.查看分数

                6.学员为课程交学费(可选)

4、用例价值

        为某学校解决了课程管理问题

5、约束和限制

        无

二、领域模型

找名词: 

管理员、学校、课程、班级、学员、讲师、上课记录、作业、分数、成绩
筛选:去掉与行业或者说领域无关的名词

加属性:

名词属性备注
管理员-具备所有权限,对于选课系统来说,并不需要管理员的属性,因此在领域模型中,管理员是没有属性的
学校学校名,地址,课程列表
课程课程名,周期,价钱,大纲
学员学员名,年龄,学校,课程
讲师讲师名
上课记录课程节次,日期
学习记录学员名、上课记录、签到状态、签到日期、成绩

画图连关系:

三、设计模型

        设计模型的实现较为复杂,具体步骤可查看年会答题系统中的设计模型小节,本次我们将用到 MVC 模型(感兴趣的可以先自行百度一下,该模型框架将会在 Web 框架中学习到)来进行架构的设计

三层架构(MVC):

        - 用户视图层

                - 用于与用户进行交互的

                - 小的逻辑判断,比如注册功能中两次密码是否一致的校验
                - core
                    - src.py  主视图
                    - admin.py  管理员视图
                    - student.py  学员视图
                    - teacher.py  讲师视图

        - 逻辑接口层

                - 核心业务逻辑的处理

                - interface
                    - admin_interface.py
                    - student_interface.py
                    - teacher_interface.py

        - 数据处理层

                - 做数据的处理,比如数据的 增、删、查、改

                - db

                    - models.py

                        - 用于存放所有类,管理所有的类
                        - Base:
                            # 保存数据
                            - save(self):
                                db_handler.save_data()

                              @classmethod
                            - select(cls, username):
                                obj = db_handler.select_data(cls, username)
                               return obj

                       - Admin(Base)
                           - __init__(self, admin_name, pwd):
                               self.user = admin_name
                               self.pwd = pwd

                            # 管理员的创建学校方法
                            - create_school():
                                school_obj = School()
                                school_obj.save()

                           # 管理员的创建课程方法
                            - create_course(school_obj, course_name):
                               course_obj = Course()
                               course_obj.save()
                               school_obj.course_list.append(course_name)

                            # 管理员的创建老师方法
                           - create_teacher(self, teacher_name, teacher_pwd):
                               tea_obj = Teacher(teacher_name, teacher_pwd)
                               tea_obj.save()


                       - School(Base):
                           __init__(self, school_name, school_addr)
                                self.user = school_name
                                self.addr = school_addr
                                self.course_list = []


                        - Course(Base):
                            __init__(self, course_name):
                                self.user = course_name
                                self.student_list = []

                        - Teacher(Base):
                            __init__(self, teacher_name, teacher_pwd):
                               self.user = teacher_name
                               self.pwd = teacher_pwd
                               self.course_list_from_teacher = []


                   - db_handler.py
                        - save_data(obj)  保存 对象
                           - 拼接文件夹,以类名当做文件夹管理文件
                           class_name = obj.__class__.__name__
                           - 再拼接文件,然后把对象通过pickle序列化到pickle文件中


                        - select_data(cls, username):
                           - 拼接文件夹,以类名当做文件夹管理文件
                           class_name = cls.__name__
                           - 再拼接文件,然后把通过pickle反序列化得到pickle文件中的对象


                       - ATM + 购物车(可选实现)
                            - 存放 json格式的数据
                            - dict --> json

                       - 选课系统(可选实现)
                            - pickle 保存对象
                            - object ——> pickle

四、实现模型

目录结构设计:

CourseSystem/

| --  conf/

|      | --  settings.py

|      |

| --  core/

|      | -- src.py

|      | -- admin.py

|      | -- student.py

|      | -- teacher.py

|

| --  db/

|      | -- Admin/

|      | -- Course/

|      | -- School/

|      | -- Student/

|      | -- Teacher/

|      | -- models.py

|      | -- db_handler.py

|

| --  interface/

|      | -- admin_interface.py

|      | -- common_interface.py

|      | -- student_interface.py

|      | -- teacher_interface.py

|

| --  lib/

|      | -- common.py

|

| --  start.py

|

| --  README

start.py:程序入口

"""
启动文件入口
"""

import os, sys
sys.path.append(
    os.path.dirname(__file__)
)
from core import src

if __name__ == '__main__':
    src.run()

setting.py:程序设置

import os

BASE_PATH = os.path.dirname(
    os.path.dirname(__file__)
)

DB_PATH = os.path.join(
    BASE_PATH, 'db'
)

core/src.py:用户视图层的主视图

"""
用户视图层的 主视图
"""

from core import admin
from core import student
from core import teacher

func_dict = {
    '1': admin.admin_view,
    '2': student.student_view,
    '3': teacher.teacher_view,
}
def run():
    while True:
        print('''
        ====== 欢迎来到选课系统 ======
              1.管理员功能
              2.学生功能
              3.老师功能
        =========== end =============
        ''')

        choice = input('请输入功能编号: ').strip()

        if choice not in func_dict:
            print('输入有误,请重新输入!')
            continue

        func_dict.get(choice)()

core/admin.py:管理员视图

"""
管理员视图
"""
from interface import admin_interface
from interface import common_interface
from lib import common

admin_info = {
    'user': None
}


# 管理员注册
def register():
    while True:
        username = input('请输入用户名: ').strip()
        password = input('请输入密码: ').strip()
        re_password = input('请确认密码: ').strip()

        # 小的逻辑判断
        if password == re_password:
            # 调用接口层,管理员注册接口
            flag, msg = admin_interface.admin_register_interface(
                username, password
            )

            if flag:
                print(msg)
                break

            else:
                print(msg)

        else:
            print('两次密码不一致,请重新输入')


# 管理员登录
def login():
    while True:
        username = input('请输入用户名: ').strip()
        password = input('请输入密码: ').strip()

        # 1.调用管理员登录接口
        flag, msg = common_interface.login_interface(
            username, password, user_type='admin'
        )
        if flag:
            print(msg)
            # 记录当前用户登录状态
            # 可变类型不需要global
            admin_info['user'] = username
            break

        else:
            print(msg)


# 管理员创建学校
@common.auth('admin')
def create_school():
    while True:
        # 1.让用户输入学校的名称与地址
        school_name = input('请输入学校名称: ').strip()
        school_addr = input('请输入学校地址: ').strip()

        # 2.调用接口,保存学校
        flag, msg = admin_interface.create_school_interface(
            # 学校名、学校地址、创建学校的管理员
            school_name, school_addr, admin_info.get('user')
        )

        if flag:
            print(msg)
            break

        else:
            print(msg)


# 管理员创建课程
@common.auth('admin')
def create_course():
    while True:
        # 1.让管理员先选择学校
        # 1.1 调用接口,获取所有学校的名称并打印
        flag, school_list_or_msg = common_interface.get_all_school_interface()
        if not flag:
            print(school_list_or_msg)
            break

        for index, school_name in enumerate(school_list_or_msg):
            print(f'编号: {index}    学校名: {school_name}')

        choice = input('请输入学校编号: ').strip()

        if not choice.isdigit():
            print('请输入数字')
            continue

        choice = int(choice)

        if choice not in range(len(school_list_or_msg)):
            print('请输入正确编号!')
            continue

        # 获取选择后的学校名字
        school_name = school_list_or_msg[choice]

        # 2.选择学校后,再输入课程名称
        course_name = input('请输入需要创建的课程名称: ').strip()

        # 3.调用创建课程接口,让管理员去创建课程
        flag, msg = admin_interface.create_course_interface(
            # 传递学校的目的,是为了关联课程
            school_name, course_name, admin_info.get('user')
        )

        if flag:
            print(msg)
            break
        else:
            print(msg)


# 管理员创建老师
@common.auth('admin')
def create_teacher():
    while True:
        # 1.让管理员输入创建的老师名字
        teacher_name = input('请输入老师的名字: ').strip()
        # 2.调用接口创建老师
        flag, msg = admin_interface.create_teacher_interface(
            teacher_name, admin_info.get('user'))

        if flag:
            print(msg)
            break

        else:
            print(msg)


func_dict = {
    '1': register,
    '2': login,
    '3': create_school,
    '4': create_course,
    '5': create_teacher,
}


# 管理员视图函数
def admin_view():
    while True:
        print('''
        - 1.注册
        - 2.登录
        - 3.创建学校
        - 4.创建课程
        - 5.创建讲师
        ''')

        choice = input('请输入功能编号: ').strip()

        if choice == 'q':
            admin_info['user'] = None
            break

        if choice not in func_dict:
            print('输入有误,请重新输入!')
            continue

        func_dict.get(choice)()

core/student.py:学员视图

"""
学生视图
"""
from docutils.nodes import attention

from lib import common
from interface import student_interface
from interface import common_interface

student_info = {'user': None}


# 学生注册
def register():
    while True:
        username = input('请输入用户名: ').strip()
        password = input('请输入密码: ').strip()
        re_password = input('请确认密码: ').strip()

        # 小的逻辑判断
        if password == re_password:

            # 调用接口层,学生注册接口
            flag, msg = student_interface.student_register_interface(
                username, password
            )

            if flag:
                print(msg)
                break

            else:
                print(msg)

        else:
            print('两次密码不一致,请重新输入')


# 学生登录
def login():
    while True:
        username = input('请输入用户名: ').strip()
        password = input('请输入密码: ').strip()

        # 1.调用管理员登录接口
        flag, msg = common_interface.login_interface(
            username, password, user_type='student'
        )
        if flag:
            print(msg)
            # 记录当前用户登录状态
            # 可变类型不需要global
            student_info['user'] = username
            break

        else:
            print(msg)


# 学生选择学校
@common.auth('student')
def choice_school():
    while True:
        # 1、获取所有学校,让学生选择
        flag, school_list = common_interface.get_all_school_interface()
        if not flag:
            print(school_list)
            break

        for index, school_name in enumerate(school_list):
            print(f'编号: {index}   学校名: {school_name}')

        # 2、让学生输入学校编号
        choice = input('请输入选择的学校编号: ').strip()
        if not choice.isdigit():
            print('输入有误')
            continue

        choice = int(choice)

        if choice not in range(len(school_list)):
            print('输入编号有误!')
            continue

        school_name = school_list[choice]

        # 3、开始调用学生选择学校接口
        flag, msg = student_interface.add_school_interface(
            school_name, student_info.get('user'))

        if flag:
            print(msg)
            break

        else:
            print(msg)
            break


# 学生选择课程
@common.auth('student')
def choice_course():
    while True:
        # 1、先获取 "当前学生" 所在学校的课程列表
        flag, course_list = student_interface.get_course_list_interface(
            student_info.get('user')
        )
        if not flag:
            print(course_list)
            break

        # 2、打印课程列表,并让用户选择课程
        for index, course_name in enumerate(course_list):
            print(f'编号: {index}   课程名: {course_name}')

        # 2、让学生输入学校编号
        choice = input('请输入选择的学校编号: ').strip()
        if not choice.isdigit():
            print('输入有误')
            continue

        choice = int(choice)

        if choice not in range(len(course_list)):
            print('输入编号有误!')
            continue
        # 3、获取选择的课程名称
        course_name = course_list[choice]

        # 4、调用学生选择课程接口
        flag, msg = student_interface.add_course_interface(
            course_name, student_info.get('user')
        )

        if flag:
            print(msg)
            break
        else:
            print(msg)


# 上课
@common.auth('student')
def attend_course():
    while True:
        # 1、先获取 "当前学生" 已选的课程列表
        flag, course_list = student_interface.get_course_list_for_student_interface(
            student_info.get('user')
        )

        if not flag:
            print(course_list)
            break

        # 2、打印课程列表,并让用户选择课程
        for index, course_name in enumerate(course_list):
            print(f'编号: {index}   课程名: {course_name}')

        # 3、让学生输入课程编号
        choice = input('请输入选择的课程编号: ').strip()
        if not choice.isdigit():
            print('输入有误')
            continue

        choice = int(choice)

        if choice not in range(len(course_list)):
            print('输入编号有误!')
            continue

        # 3、获取选择的课程名称
        course_name = course_list[choice]

        # 4、调用学生上课接口,并留下上课记录
        flag, msg = student_interface.attend_course_for_student_interface(
            course_name, student_info.get('user')
        )

        if flag:
            print(msg)
            break

# 学生查看课程分数
@common.auth('student')
def check_score():
    # 1、直接调用查看分数接口
    score_dict = student_interface.check_score_interface(
        student_info.get('user')
    )

    if not score_dict:
        print('没有选择课程!')

    print(score_dict)


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


def student_view():
    while True:
        print('''
        - 1.注册
        - 2.登录功能
        - 3.选择校区
        - 4.选择课程
        - 5.上课
        - 6.查看分数
        ''')

        choice = input('请输入功能编号: ').strip()

        if choice == 'q':
            break

        if choice not in func_dict:
            print('输入有误,请重新输入!')
            continue

        func_dict.get(choice)()

core/teacher.py:讲师视图

"""
老师视图
"""
from lib import common
from interface import common_interface
from interface import teacher_interface

teacher_info = {'user': None}


# 老师登录
def login():
    while True:
        username = input('请输入用户名: ').strip()
        password = input('请输入密码: ').strip()

        # 1.调用管理员登录接口
        flag, msg = common_interface.login_interface(
            username, password, user_type='teacher'
        )
        if flag:
            print(msg)
            # 记录当前用户登录状态
            # 可变类型不需要global
            teacher_info['user'] = username
            break

        else:
            print(msg)


# 查看教授课程
@common.auth('teacher')
def check_course():
    flag, course_list = teacher_interface.check_course_interface(
        teacher_info.get('user')
    )
    if flag:
        print(course_list)
    else:
        print(course_list)


# 选择教授课程
@common.auth('teacher')
def choose_course():
    while True:
        # 1、先打印所有学校,并选择
        flag, school_list = common_interface.get_all_school_interface()
        if not flag:
            print(school_list)
            break

        for index, school_name in enumerate(school_list):
            print(f'编号: {index}   学校名: {school_name}')

        choice = input('请输入选择的学校编号: ').strip()
        if not choice.isdigit():
            print('输入有误')
            continue

        choice = int(choice)

        if choice not in range(len(school_list)):
            print('输入编号有误!')
            continue

        # 获取选择的学校名称
        school_name = school_list[choice]

        # 2、从选择的学校中获取所有的课程
        flag2, course_list = common_interface.get_course_in_school_interface(
            school_name
        )
        if not flag2:
            print(course_list)
            break

        for index2, course_name in enumerate(course_list):
            print(f'编号: {index2}   课程名: {course_name}')

        choice2 = input('请输入选择的课程编号: ').strip()

        if not choice2.isdigit():
            print('输入有误')
            continue

        choice2 = int(choice2)

        if choice2 not in range(len(course_list)):
            print('输入编号有误!')
            continue

        # 获取选择的课程名称
        course_name = course_list[choice2]

        # 3、调用选择教授课程接口,将该课程添加到老师课程列表中
        flag3, msg = teacher_interface.add_course_interface(
            course_name, teacher_info.get('user')
        )
        if flag3:
            print(msg)
            break
        else:
            print(msg)


# 查看课程下学生
@common.auth('teacher')
def check_stu_from_course():
    while True:
        # 1、调用获取当前老师下所有的课程接口
        flag, course_list = teacher_interface.check_course_interface(
            teacher_info.get('user')
        )
        if not flag:
            print(course_list)
            break

        # 2、打印所有课程,并让老师选择
        for index, course_name in enumerate(course_list):
            print(f'编号: {index}   课程名: {course_name}')

        choice = input('请输入选择的课程编号: ').strip()

        if not choice.isdigit():
            print('输入有误')
            continue

        choice = int(choice)

        if choice not in range(len(course_list)):
            print('输入编号有误!')
            continue

        # 3、获取选择的课程名称
        course_name = course_list[choice]

        # 4、利用当前课程名称获取所有学生
        flag2, student_list = teacher_interface.get_student_interface(
            course_name, teacher_info.get('user')
        )

        if flag2:
            print(student_list)
            break
        else:
            print(student_list)
            break


# 修改学生分数
@common.auth('teacher')
def change_score_from_student():
    '''
    # 1、先获取老师下所有的课程,并选择
    # 2、获取选择的课程下所有的学生,并选择修改的学生
    # 3、调用修改学生分数接口修改分数
    '''
    while True:
        # 1、调用获取当前老师下所有的课程接口
        flag, course_list = teacher_interface.check_course_interface(
            teacher_info.get('user')
        )
        if not flag:
            print(course_list)
            break

        # 2、打印所有课程,并让老师选择
        for index, course_name in enumerate(course_list):
            print(f'编号: {index}   课程名: {course_name}')

        choice = input('请输入选择的课程编号: ').strip()

        if not choice.isdigit():
            print('输入有误')
            continue

        choice = int(choice)

        if choice not in range(len(course_list)):
            print('输入编号有误!')
            continue

        # 3、获取选择的课程名称
        course_name = course_list[choice]

        # 4、利用当前课程名称获取所有学生
        flag2, student_list = teacher_interface.get_student_interface(
            course_name, teacher_info.get('user')
        )

        if not flag2:
            print(student_list)
            break

        # 5、打印所有学生让老师选择
        for index2, student_name in enumerate(student_list):
            print(f'编号:{index2}   学生名: {student_name}')

        choice2 = input('请输入学生编号: ').strip()

        choice2 = int(choice2)

        if choice2 not in range(len(student_list)):
            print('输入编号有误!')
            continue

        # 获取选择的课程名称
        student_name = student_list[choice2]

        # 老师输入需要修改的分数
        score = input('请输入需要修改的成绩:').strip()
        if not score.isdigit():
            continue

        score = int(score)

        # 6、调用修改学生分数接口修改分数
        flag3, msg = teacher_interface.change_score_interface(
            course_name, student_name,
            score, teacher_info.get('user')
        )

        if flag3:
            print(msg)
            break


func_dict = {
    '1': login,
    '2': check_course,
    '3': choose_course,
    '4': check_stu_from_course,
    '5': change_score_from_student,
}


def teacher_view():
    while True:
        print('''
        - 1.登录
        - 2.查看教授课程
        - 3.选择教授课程
        - 4.查看课程下学生
        - 5.修改学生分数
        ''')

        choice = input('请输入功能编号: ').strip()

        if choice == 'q':
            break

        if choice not in func_dict:
            print('输入有误,请重新输入!')
            continue

        func_dict.get(choice)()

db/models.py:用于存放所有类,管理所有的类,即接口相关功能具体实现都是这里的代码来实现的

"""
用于存放所有类(学校类、学员类、课程类、讲师类、管理员类)的管理功能
"""
from db import db_handler


# 父类,让所有子类都继承 select 与 save方法
class Base:
    # 查看数据  ----> 登录、查看数据库
    @classmethod
    def select(cls, username):  # School, school_name
        # obj: 对象   or   None
        obj = db_handler.select_data(cls, username)
        return obj

    # 保存数据 ---> 注册、保存、更新数据
    def save(self):
        # 让db_handler中的save_data帮我保存对象数据
        db_handler.save_data(self)


# 管理员类
class Admin(Base):
    # 调用类的时候触发
    # username, password
    def __init__(self, user, pwd):
        # 给当前对象赋值
        self.user = user
        self.pwd = pwd

    # 创建学校
    def create_school(self, school_name, school_addr):
        # 该方法内部来调用学校类实例化的得到对象,并保存
        school_obj = School(school_name, school_addr)
        school_obj.save()

    # 创建课程
    def create_course(self, school_obj, course_name):
        # 1.调用课程类,实例化创建课程
        course_obj = Course(course_name)
        course_obj.save()
        # 2.获取当前学校对象,并将课程添加到课程列表中
        school_obj.course_list.append(course_name)
        # 3.更新学校数据
        school_obj.save()

    # 创建讲师
    def create_teacher(self, teacher_name, teacher_pwd):
        # 1.调用老师类,实例化的到老师对象,并保存
        teacher_obj = Teacher(teacher_name, teacher_pwd)
        teacher_obj.save()


# 学校类
class School(Base):
    def __init__(self, name, addr):
        # 必须写: self.user,
        # 因为db_handler里面的select_data统一规范
        self.user = name
        self.addr = addr
        # 课程列表: 每所学校都应该有相应的课程
        self.course_list = []


# 学生类
class Student(Base):

    def __init__(self, user, pwd):
        self.user = user
        self.pwd = pwd
        # 每个学生只能有一个校区
        self.school = None
        # 一个学生可以选择多门课程
        self.course_list = []
        # 学生课程分数
        self.score_dict = {}  # {"course_name": 0}
        # 学生上课记录
        self.course_log_dict = {}

    # 学生添加学校方法
    def add_school(self, school_name):
        self.school = school_name
        self.save()

    # 学生添加课程方法
    def add_course(self, course_name):
        # 1、学生课程列表添加课程
        self.course_list.append(course_name)
        # 2、给学生选择的课程设置默认分数
        self.score_dict[course_name] = 0
        self.save()
        # 3、学生选择的课程对象,添加学生
        course_obj = Course.select(course_name)
        course_obj.student_list.append(
            self.user
        )
        course_obj.save()

    # 学生上课
    def add_attend_course_log(self, course_name, time):
        # 1、学生上课记录
        if course_name in self.course_log_dict:
            time_log = self.course_log_dict[course_name]
            # 每上一次课追加一次
            time_log.append(time)
        else:
            time_log = [time]
        self.course_log_dict[course_name] = time_log
        self.save()

# 课程类
class Course(Base):
    def __init__(self, course_name):
        self.user = course_name
        self.student_list = []


# 老师类
class Teacher(Base):
    def __init__(self, teacher_name, teacher_pwd):
        self.user = teacher_name
        # self.pwd需要统一
        self.pwd = teacher_pwd
        self.course_list_from_tea = []

    # 老师查看教授课程方法
    def show_course(self):
        return self.course_list_from_tea

    # 老师添加课程方法
    def add_course(self, course_name):
        self.course_list_from_tea.append(
            course_name
        )
        self.save()

    # 老师获取课程下学生方法
    def get_student(self, course_name):
        course_obj = Course.select(course_name)
        return course_obj.student_list

    # 老师修改学生分数方法
    def change_score(self, course_name, student_name, score):
        # 1、获取学生对象
        student_obj = Student.select(student_name)

        # 2、再给学生对象中的课程修改分数
        student_obj.score_dict[course_name] = score
        student_obj.save()

db/db_handler.py:用于数据操作,保存之类的

"""
用于保存对象与获取对象
"""
import os
import pickle
from conf import settings


# 保存数据
def save_data(obj):
    """
    1.获取对象的保存文件夹路径
    以类名 当做 文件夹的名字
    obj.__class__: 获取当前对象的类
    obj.__class__.__name__: 获取类的名字
    """
    class_name = obj.__class__.__name__
    user_dir_path = os.path.join(
        settings.DB_PATH, class_name
    )

    # 2.判断文件夹是否存在,不存在则创建文件夹
    if not os.path.exists(user_dir_path):
        os.mkdir(user_dir_path)

    # 3.拼接当前用户的pickle文件路径,, 以用户名作为文件名
    user_path = os.path.join(
        user_dir_path, obj.user  # 当前用户名字
    )

    # 4.打开文件,保存对象, 通过pickle
    with open(user_path, 'wb') as f:
        pickle.dump(obj, f)


# 查看数据
def select_data(cls, username):  # 类, username
    # 由cls类获取类名
    class_name = cls.__name__
    user_dir_path = os.path.join(
        settings.DB_PATH, class_name
    )

    # 2.判断文件夹是否存在,不存在则创建文件夹
    if not os.path.exists(user_dir_path):
        os.mkdir(user_dir_path)

    # 3.拼接当前用户的pickle文件路径,, 以用户名作为文件名
    user_path = os.path.join(
        user_dir_path, username  # 当前用户名字
    )

    # 4.判断文件如果存在,再打开,并返回,若不存在,则代表用户不存在
    if os.path.exists(user_path):
        # 5.打开文件,获取对象
        with open(user_path, 'rb') as f:
            obj = pickle.load(f)
            return obj

interface/admin_interface.py:管理员接口

"""
管理员接口
"""
from db import models


# 管理员注册接口
def admin_register_interface(username, password):
    # 1.判断用户是否存在
    # 调用Admin类中的,select方法,
    # 由该方法去调用db_handler中的select_data功能获取对象
    admin_obj = models.Admin.select(username)

    # 1.1) 若存在不允许注册,返回用户已存在给视图层
    if admin_obj:
        return False, '用户已存在!'

    # 1.2) 若不存在则允许注册,调用类实例化得到对象并保存
    admin_obj = models.Admin(username, password)
    # 对象调用save() 会将 admin_obj传给save方法
    admin_obj.save()

    return True, '注册成功!'


# 管理员登录接口(被lib/common中的公共登录接口所替代)
"""
def admin_login_interface(username, password):
    # 1.判断用户是否存在
    admin_obj = models.Admin.select(username)

    # 2.若不存在,则证明用户不存在并返回给视图层
    if not admin_obj:
        return False, '用户名不存在!'

    # 3.若用户存在,则校验密码
    if password == admin_obj.pwd:
        return True, '登录成功! '
    else:
        return False, '密码错误!'
"""


# 管理员创建学校接口
def create_school_interface(school_name, school_addr, admin_name):
    # 1.查看当前学校是否已存在
    # school_obj ---> 对象  or   None
    school_obj = models.School.select(school_name)

    # 2.若学校存在,则返回False告诉用户学校已存在
    if school_obj:
        return False, '学校已存在!'

    # 3.若不存在,则创建学校, 注意: (由管理员对象来创建)
    admin_obj = models.Admin.select(admin_name)
    # 由管理员来调用创建学校方法,并传入学校的名字与地址
    admin_obj.create_school(
        school_name, school_addr
    )

    # 4.返回创建学校成功给视图层
    return True, f'[{school_name}]学校创建成功!'


# 管理员创建课程接口
def create_course_interface(school_name, course_name, admin_name):
    # 1.查看课程是否存在
    # 1.1 先获取学校对象中的课程列表
    school_obj = models.School.select(school_name)
    # 1.2 判断当前课程是否存在课程列表中
    if course_name in school_obj.course_list:
        return False, '当前课程已存在!'

    # 1.2 若课程不存在,则创建课程, 由管理员来创建
    admin_obj = models.Admin.select(admin_name)
    admin_obj.create_course(
        school_obj, course_name
    )

    return True, f'[{course_name}] 课程创建成功, 绑定给[{school_name}]校区!'


# 管理员创建老师接口
def create_teacher_interface(teacher_name, admin_name, teacher_pwd='123'):
    # 1.判断老师是否存在
    teacher_obj = models.Teacher.select(teacher_name)

    # 2.若存在,则返回不能创建
    if teacher_obj:
        return False, '老师已存在!'

    # 3.若不存在,则创建老师,让 管理员 来创建
    admin_obj = models.Admin.select(admin_name)
    admin_obj.create_teacher(teacher_name, teacher_pwd)

    return True, f'[{teacher_name}]老师创建成功!初始密码为[{teacher_pwd}]'

interface/common_interface.py:公共接口

"""
公共接口
"""
import os
from conf import settings
from db import models


# 获取所有学校名称接口
def get_all_school_interface():
    # 1.获取学校文件夹路径
    school_dir = os.path.join(
        settings.DB_PATH, 'School'
    )

    # 2.判断文件夹是否存在
    if not os.path.exists(school_dir):
        return False, '没有学校,请先联系管理员'

    # 3.文件夹若存在,则获取文件夹中所有文件的名字
    school_list = os.listdir(school_dir)
    return True, school_list


# 公共登录接口
def login_interface(user, pwd, user_type):
    if user_type == 'admin':
        obj = models.Admin.select(user)

    elif user_type == 'student':
        obj = models.Student.select(user)

    elif user_type == 'teacher':
        obj = models.Teacher.select(user)

    else:
        return False, '登录角色不对,请输入角色'

    # 1.判断用户是否存在
    if obj:
        # 2.若用户存在,则校验密码
        if pwd == obj.pwd:
            return True, '登录成功! '
        else:
            return False, '密码错误!'

    else:
        # 3.若不存在,则证明用户不存在并返回给视图层
        return False, '用户名不存在!'


# 获取学校下所有课程接口
def get_course_in_school_interface(school_name):

    # 1、获取学校对象
    school_obj = models.School.select(school_name)

    # 2、获取学校对象下所有课程
    course_list = school_obj.course_list

    if not course_list:
        return False, '该学校没有课程'

    return True, course_list

interface/student_interface.py:学员接口

"""
学生接口层
"""
from db import models
import datetime


# 学生注册接口
def student_register_interface(user, pwd):
    # 1.判断用户是否存在
    # 调用Student类中的,select方法,
    # 由该方法去调用db_handler中的select_data功能获取对象
    student_obj = models.Student.select(user)

    # 1.1) 若存在不允许注册,返回用户已存在给视图层
    if student_obj:
        return False, '学生用户已存在!'

    # 1.2) 若不存在则允许注册,调用类实例化得到对象并保存
    student_obj = models.Student(user, pwd)
    # 对象调用save() 会将 admin_obj传给save方法
    student_obj.save()

    return True, '注册成功!'


# 学生登录接口(被lib/common中的公共登录接口所替代)
"""
def student_login_interface(user, pwd):
    # 1.判断用户是否存在
    student_obj = models.Student.select(user)

    # 2.若不存在,则证明用户不存在并返回给视图层
    if not student_obj:
        return False, '用户名不存在!'

    # 3.若用户存在,则校验密码
    if pwd == student_obj.pwd:
        return True, '登录成功! '
    else:
        return False, '密码错误!'
"""


# 学生选择学校接口
def add_school_interface(school_name, student_name):
    # 1、判断当前学生是否存在学校
    student_obj = models.Student.select(student_name)

    if student_obj.school:
        return False, '当前学生已经选择过学校了!'

    # 2、若不存在学校,则给调用学生对象中选择学校的方法,实现学生添加学校
    student_obj.add_school(school_name)
    return True, '选择学校成功!'


# 获取学生所在学校所有课程接口
def get_course_list_interface(student_name):
    # 1、获取当前学生对象
    student_obj = models.Student.select(student_name)
    school_name = student_obj.school
    # 2、判断当前学生是有学校,若没有则返回False
    if not school_name:
        return False, '没有学校,请先选择学校'

    # 3、开始获取学校对象中的课程列表
    school_obj = models.School.select(school_name)

    # 3.1、判断当前学校中是否有课程,若没有,则联系管理员
    course_list = school_obj.course_list
    if not course_list:
        return False, '没有课程,请先联系管理员创建'

    # 3.2、若有则,返回课程列表
    return True, course_list


# 学生选择学校接口
def add_course_interface(course_name, student_name):
    # 1、先判断当前课程是否已经存在学生课程列表中
    student_obj = models.Student.select(student_name)

    if course_name in student_obj.course_list:
        return False, '该课程已经选择过了!'

    # 2、调用学生对象中添加课程的方法
    student_obj.add_course(course_name)

    return True, f'[{course_name}] -- 课程添加成功!'


# 学生查看已选课程接口
def get_course_list_for_student_interface(student_name):
    # 1、获取当前学生对象
    student_obj = models.Student.select(student_name)
    # 2、开始获取学生对象中的课程列表
    course_list = student_obj.course_list

    # 3、没有课程让学生选择课程
    if not course_list:
        return False, '没有课程,请先选择课程'

    # 4、若有则,返回课程列表
    return True, course_list


# 学生上课接口
def attend_course_for_student_interface(course_name, student_name):
    # 1、获取当前学生对象
    student_obj = models.Student.select(student_name)

    # 2、进入课堂,产生上课记录
    time = datetime.datetime.now()
    student_obj.add_attend_course_log(course_name, time)

    return True, '上完课了!'


# 学生会查看分数接口
def check_score_interface(student_name):
    student_obj = models.Student.select(student_name)
    if student_obj.score_dict:
        return student_obj.score_dict

interface/teacher_interface.py:讲师接口

"""
老师接口层
"""
from db import models


# 老师查看课程接口
def check_course_interface(teacher_name):
    # 1、获取当前老师对象
    teacher_obj = models.Teacher.select(teacher_name)

    # 2、判断老师对象中课程列表是否有值
    # 让老师对象,调用查看教授课程方法,返回课程
    # course_list = teacher_obj.course_list_from_tea
    course_list = teacher_obj.show_course()

    # 3、若有则返回True, 无则返回False
    if not course_list:
        return False, '老师没有选择课程'

    return True, course_list


# 老师添加课程接口
def add_course_interface(course_name, teacher_name):
    # 1、获取当前老师对象
    teacher_obj = models.Teacher.select(teacher_name)

    # 2、判断当前课程是否在老师的课程列表中
    course_list = teacher_obj.course_list_from_tea
    if course_name in course_list:
        return False, '该课程已存在!'

    # 3、若不存在,则添加该课程到老师课程列表中
    teacher_obj.add_course(course_name)

    return True, '添加课程成功!'


# 老师获取课程下学生接口
def get_student_interface(course_name, teacher_name):
    # 1、获取当前老师对象
    teacher_obj = models.Teacher.select(teacher_name)

    # 2、让当前老师对象,调用获取课程下所有学生功能
    student_list = teacher_obj.get_student(course_name)

    # 3、判断课程下是否有学生
    if not student_list:
        return False, '学生没有选择该课程'

    return True, student_list


# 老师修改分数接口
def change_score_interface(course_name, student_name, score, teacher_name):

    # 1、获取老师对象
    teacher_obj = models.Teacher.select(teacher_name)

    # 2、让老师对象调用修改分数方法
    teacher_obj.change_score(course_name, student_name, score)

    return True, '修改分数成功!'

lib/common.py:公共方法

"""
公共方法
"""

# 多用户登录认证装饰器
def auth(role):
    """
    :param role: 角色 ---》 管理员、学生、老师
    :return:
    """
    from core import admin, student, teacher
    # 登录认证装饰器
    def login_auth(func):
        def inner(*args, **kwargs):
            if role == 'admin':
                if admin.admin_info['user']:
                    res = func(*args, **kwargs)
                    return res
                else:
                    admin.login()

            elif role == 'student':
                if student.student_info['user']:
                    res = func(*args, **kwargs)
                    return res
                else:
                    student.login()

            elif role == 'teacher':
                if teacher.teacher_info['user']:
                    res = func(*args, **kwargs)
                    return res
                else:
                    teacher.login()

            else:
                print('当前视图没有权限')

        return inner

    return login_auth

代码链接:https://gitcode.com/zjw529507929/CourseSystem 

效果如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/948238.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

游泳溺水识别数据集,对25729张图片进行YOLO,COCO JSON, VOC XML 格式的标注,溺水平均识别率在89.9%

游泳溺水识别数据集,对25729张图片进行YOLO,COCO JSON, VOC XML 格式的标注,溺水识别率在92% 训练结果 数据集和标签 验证 游泳测试视频 根据测试的视频来获取检测结果: 游泳测试视频的置信度设置60% 检测结果如下&…

性能测试03|JMeter:断言、关联、web脚本录制

目录 一、断言 1、响应断言 2、json断言 3、持续时间断言 二、关联 1、正则表达式介绍 2、正则表达式提取器 3、Xpath提取器 4、JSON提取器 5、JMeter属性 三、web脚本录制 一、断言 定义:让程序自动判断实际的返回结果是否与预期结果保持一致 自动校验…

MetaGPT - 多Agent框架

文章目录 一、关于 MetaGPT功能介绍快速开始的演示视频教程 二、安装Pip安装Docker安装 一、关于 MetaGPT MetaGPT 为GPTs分配不同的角色,以形成一个协作实体来完成复杂的任务。 github : https://github.com/geekan/MetaGPTtwitter : https://twitter.com/MetaGP…

Qt窗口获取Tftpd32_svc服务下载信息

前言 一个由Qt开发的Windows小工具需要布置Tftp协议服务端来支持设备下载数据,并显示下载列表(进度、下载源等)。 考虑开发方便,优先使用了Qtftp方案,经测试发现,不够稳定,会有下载超时的情况&a…

xml格式化(3):增加头部声明

前言 这篇文章&#xff0c;是用来增加头部声明。 正文 from lxml import etreedef pretty_print(element, level0, indent" "):result ""# 判断元素是否为注释节点if isinstance(element, etree._Comment):result f"{indent * level}<!--{el…

python +tkinter绘制彩虹和云朵

python tkinter绘制彩虹和云朵 彩虹&#xff0c;简称虹&#xff0c;是气象中的一种光学现象&#xff0c;当太阳光照射到半空中的水滴&#xff0c;光线被折射及反射&#xff0c;在天空上形成拱形的七彩光谱&#xff0c;由外圈至内圈呈红、橙、黄、绿、蓝、靛、紫七种颜色。事实…

【Linux】定时运行shell脚本

1、at命令 at命令允许指定Linux系统何时运行脚本&#xff0c;它会将作业提交到队列中&#xff0c;指定shell在什么时候运行该作业。 at 的守护进程 atd 在后台运行&#xff0c;在作业队列中检查待运行的作业。 at 守护进程会检查系统的一个特殊目录&#xff08;一般位于/var/…

vue3 css实现文字输出带光标显示,文字输出完毕,光标消失的效果

Vue实现过程如下&#xff1a; <template><div ><p ref"dom_element" class"typing" :class"{over_fill: record_input_over}"></p></div> </template> <script setup> import {onMounted, ref} from…

数据库高安全—角色权限:角色创建角色管理

目录 3.1 角色创建 3.2 角色管理 书接上文openGauss安全整体架构&安全认证&#xff0c;从安全整体架构与安全认证两方面&#xff0c;对高斯数据库的高安全性能进行了解读&#xff0c;本篇我们将从角色创建和角色管理两方面对高斯数据库的角色权限进行介绍。 3.1 角色创建…

【U8+】用友U8软件中,出入库流水输出excel的时候提示报表输出引擎错误。

【问题现象】 通过天联高级版客户端登录拥有U8后&#xff0c; 将出入库流水输出excel的时候&#xff0c;提示报表输出引擎错误。 进行报表输出时出现错误&#xff0c;错误信息&#xff1a;找不到“fd6eea8b-fb40-4ce4-8ab4-cddbd9462981.htm”。 如果您正试图从最近使用的文件列…

《GICv3_Software_Overview_Official_Release_B》学习笔记

1.不同版本的 GIC 架构及其主要功能如下图所示&#xff1a; 2.GICv2m&#xff08;Generic Interrupt Controller Virtualization Model&#xff09;是针对ARM架构的GIC&#xff08;通用中断控制器&#xff09;的一种扩展&#xff0c; GICv2m扩展为虚拟化环境中的中断管理提供了…

【循环神经网络】RNN介绍

在人工神经网络中&#xff0c;”浅层网络”是指具有一个输入层、一个输出层和最多一个没有循环连接的隐藏层的网络。随着层数的增加&#xff0c;网络的复杂性也在增加。更多的层或循环连接通常会增加网络的深度&#xff0c;并使其能够提供不同级别的数据表示和特征提取&#xf…

C#调用Lua

目录 xLua导入 打包工具导入 单例基类导入与AB包管理器导入 Lua解析器 文件加载与重定向 Lua解析器管理器 全局变量获取 全局函数获取 对于无参数无返回值 对于有参数有返回值 对于多返回值 对于变长参数 完整代码 List与Dictionary映射Table 类映射Table 接口映射…

麒麟操作系统服务架构保姆级教程(七)Nginx+PHP+Mysql部署服务

上边几篇文章已经交过大家二进制部署nginx和php&#xff0c;现在咱们打通nginx和php&#xff0c;mysql和php&#xff0c;开始部署服务&#xff0c;学会部署服务之后就可以开始学习负载均衡啦&#xff0c;话不多说&#xff0c;咱们直接开始~~~ 目录 一、.nginx部署 二、安装PH…

开源模型迎来颠覆性突破:DeepSeek-V3与Qwen2.5如何重塑AI格局?

不用再纠结选择哪个AI模型了&#xff01;chatTools 一站式提供o1推理模型、GPT4o、Claude和Gemini等多种选择&#xff0c;快来体验吧&#xff01; 在全球人工智能模型快速发展的浪潮中&#xff0c;开源模型正逐渐成为一股不可忽视的力量。近日&#xff0c;DeepSeek-V3和Qwen 2.…

【Java项目】基于SpringBoot的【新生宿舍管理系统】

【Java项目】基于SpringBoot的【新生宿舍管理系统】 技术简介&#xff1a;本系统使用采用B/S架构、Spring Boot框架、MYSQL数据库进行开发设计。 系统简介&#xff1a;管理员登录进入新生宿舍管理系统可以查看首页、个人中心、公告信息管理、院系管理、班级管理、学生管理、宿舍…

《learn_the_architecture_-_trustzone_for_aarch64_102418_0101_03_en》学习笔记

1.TrustZone是Arm A-profile架构中安全架构的名称。TrustZone首次在Armv6K中引入&#xff0c;Armv7-A和Armv8-A也支持。TrustZone提供两个执行环境&#xff0c;它们之间具有系统范围的硬件强制隔离。在Arm架构中&#xff0c;有两种安全状态&#xff1a;安全和非安全。在EL0、EL…

Excel | 空格分隔的行怎么导入excel?

准备工作&#xff1a;windows&#xff0c;一个记事本程序和微软的Excel软件。 打开记事本&#xff0c;选中所有内容&#xff0c;按CtrlA全选&#xff0c;然后复制(CtrlC)。 在Excel中&#xff0c;定位到你想粘贴的单元格&#xff0c;按CtrlV进行粘贴。粘贴后&#xff0c;你会在…

南京观海微电子----GH7009国宇测试盒使用

1. SPI接线 针对7009&#xff1a; 2. 国宇上位机代码准备 在主函数首尾两端加入IO2时序控制的代码、以及国语SPI有效位控制的代码&#xff08;请注意7009和其他700x使用的有效位控制不一致&#xff0c;需要用哪一款加入哪一行即可&#xff09;&#xff1a; 三、国宇SPI读的使…

Arduino Uno简介与使用方法

目录 一、Arduino Uno概述 1. 硬件特性 2. 开发环境 二、Arduino Uno的基本使用方法 1. 硬件连接 2. 软件编程 三、Arduino Uno编程基础 1. 基本语法 2. 常用函数 四、Arduino Uno应用举例 1. LED闪烁 2. 温度检测 3. 超声波测距 五、Arduino Uno的扩展与应用 1…