zoukankan      html  css  js  c++  java
  • Day7作业:选课系统

    这周的作业有点糙,迁就看吧,给大家点思路:

    readme:

    需要安装模块:
        prettytable
    
    
    测试帐号:
        1.后台管理:admin/admin   只设定了这个后台管理帐号,没有写到数据库中
        2.学生选课系统需要先注册才可登录操作,测试帐号cc/123,也可注册新帐号使用
    
    
    设计思路:
        1.使用pickle存储数据,数据类型为老师,学生,课程的对象
        2.使用流程为:创建老师-->创建课程,并关联老师-->学生注册并登录-->学生选课,上课等操作
        3.老师资产的变化是由学生选择上课或者课程事故触发的,管理员没有权限操作
        4.教师名是唯一的,作为数据标识ID
    
    本课难点:
        1.整体比较简单,难点在于上个数据库中的数据关联性.
        2.由于同一对象存到不同数据库中后,反序列化取出的值是不一样的,简要说明就是对象保存后不是引用关系
        3.所以在保存对象时,对象属性中标记了教师名称,课程名称作为引用ID来做相关数据的匹配
    

    流程图:

    目录介绍:

    目录说明:
    
    |____bin    执行目录,程序入口
    | |____init_all_data.py     初始化数据库
    | |____manage.py    管理员入口
    | |____student.py   学生入口
    |____conf   配置文件目录
    | |____setting.py   配置文件
    |____core   主程序目录
    | |____manage_sys.py    管理主程序
    | |____student.py       学生主程序
    |____data   数据库目录
    | |____manage.pickle    教师对象数据
    | |____student.pickle   学生对象数据
    | |____subject.pickle   课程对象数据
    

    代码:

    bin/init_all_data:

    #!/usr/bin/env python
    # -*-coding=utf-8-*-
    # Auther:ccorz Mail:ccniubi@163.com Blog:http://www.cnblogs.com/ccorz/
    # GitHub:https://github.com/ccorzorz
    
    import sys,os,pickle
    BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(BASE_DIR)
    # print(BASE_DIR)
    from conf.setting import *
    from core import manage_sys
    from core import student
    
    """
    系统数据初始化程序,慎重使用!!!!!
    """
    
    #将所有pickle数据库中的数据写入空列表
    manage_sys.data_flush([])
    manage_sys.subject_data_flush([])
    student.student_data_flush([])
    

    bin/manage.py

    #!/usr/bin/env python
    # -*-coding=utf-8-*-
    # Auther:ccorz Mail:ccniubi@163.com Blog:http://www.cnblogs.com/ccorz/
    # GitHub:https://github.com/ccorzorz
    
    import sys,os
    BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(BASE_DIR)
    import core.manage_sys
    
    """
    管理员后台入口,测试帐号admin/admin
    """
    
    if __name__ == '__main__':
        core.manage_sys.login()
        core.manage_sys.main()
    

    bin/student.py

    #!/usr/bin/env python
    # -*-coding=utf-8-*-
    # Auther:ccorz Mail:ccniubi@163.com Blog:http://www.cnblogs.com/ccorz/
    # GitHub:https://github.com/ccorzorz
    
    import sys,os
    BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(BASE_DIR)
    import core.student
    
    """
    学生系统入口,可注册登录,或者测试帐号cc/123
    """
    if __name__ == '__main__':
        core.student.main()
    

    conf/setting.py:

    #!/usr/bin/env python
    # -*-coding=utf-8-*-
    # Auther:ccorz Mail:ccniubi@163.com Blog:http://www.cnblogs.com/ccorz/
    # GitHub:https://github.com/ccorzorz
    import os,sys,time
    BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(BASE_DIR)
    
    """
    配置文件
    """
    
    #存储老师信息的数据文件
    manage_data_file='%s/data/manage.pickle'%BASE_DIR
    
    #存储课程信息的数据文件
    subject_data_file='%s/data/subject.pickle'%BASE_DIR
    
    #存储学生信息的数据文件
    student_data_file='%s/data/student.pickle'%BASE_DIR
    
    #定义教师类
    class Teacher:
        def __init__(self,name,age,favor):
            self.favor=favor
            self.name=name
            self.age=age
            self.asset=0
    
        def gain(self,value):
            """
            上课时老师资产增加
            :param value: 课程的课时费
            :return:
            """
            self.asset=int(self.asset)+int(value)
    
        def teach_accidents(self):
            """
            课程事故时老师资产减少
            :return:
            """
            self.asset-=1
    
    from core import manage_sys
    #定义课程类
    class Subject:
        def __init__(self,classes,value,teacher_name):#构造方法
            self.classes=classes
            self.value=int(value)
            self.teacher_name=teacher_name
    
        def attend_class(self):
            """
            课程上课,并对相应老师的资产做相应调整
            :return:
            """
            print('来上课,今天我们学%s'%self.classes)
            print(5*('%s...'%self.classes))
            time.sleep(1)
            print('齐活!下课下课!!!')
            teacher_obj,index=manage_sys.sub_match_teacher(self.classes)
            #执行老师对象的资产增加方法
            teacher_obj.gain(self.value)
            teacher_data=manage_sys.data_read()
            teacher_data[index]=teacher_obj
            manage_sys.data_flush(teacher_data)
    
        def accidents(self):
            """
            课堂事故,并对相应老师的资产做相应调整,
            :return:
            """
            print('卧槽,今天上不了课了,%s老师去做大保健了'%self.teacher_name)
            print(5*'大保健...')
            time.sleep(1)
            print('退钱退钱退钱!!!')
            teacher_obj,index=manage_sys.sub_match_teacher(self.classes)
            #执行老师对象的资产减少方法
            teacher_obj.teach_accidents()
            teacher_data=manage_sys.data_read()
            teacher_data[index]=teacher_obj
            manage_sys.data_flush(teacher_data)
    
    #定义学生的类
    class Student:
        def __init__(self,name,pwd):
            self.name=name
            self.pwd=pwd
            self.subject_classes=[]
    

    core/manage_sys.py

    #!/usr/bin/env python
    # -*-coding=utf-8-*-
    # Auther:ccorz Mail:ccniubi@163.com Blog:http://www.cnblogs.com/ccorz/
    # GitHub:https://github.com/ccorzorz
    
    import sys,os,pickle,prettytable,time
    BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(BASE_DIR)
    from conf.setting import *
    
    #定义登录状态的常量
    LOGIN_STATE=False
    
    def check_login(func):
        """
        装饰器,判断管理员权限
        :param func:
        :return:
        """
        def inner(*args,**kwargs):
            if LOGIN_STATE: #判断是否已登录
                res=func(*args,**kwargs)
                return res
            else:print('程序需要登录后才可执行!')
        return inner
    
    
    def data_read():
        """
        老师DB读取函数
        :return: 读取结果
        """
        data=pickle.load(open(manage_data_file,'rb'))
        return data
    
    
    def data_flush(args):
        """
        写入修改后的新教师类数据
        :param args: 修改后的老师数据
        :return:
        """
        pickle.dump(args,open(manage_data_file,'wb'))
    
    def subject_data_read():
        """
        读取课程类的数据
        :return: 读取结果
        """
        subject_data=pickle.load(open(subject_data_file,'rb'))
        return subject_data
    
    
    def subject_data_flush(args):
        """
        写入修改后的课程类数据
        :param args: 修改后的数据
        :return:
        """
        pickle.dump(args,open(subject_data_file,'wb'))
    
    
    def sub_match_teacher(sub_classes):
        """
        匹配课程类中的老师名称与老师类数据中的老师对象
        :param sub_classes:课程名称
        :return:匹配到的老师对象以及对应的索引
        """
        #读取课程数据
        subject_data=subject_data_read()
        #遍历课程数据,查找到课堂的名称
        for item in subject_data:
            if sub_classes==item.classes:
                teac_name=item.teacher_name
        #遍历教师数据,查找到对应老师的对象以及下标值
        teacher_data=data_read()
        for item in teacher_data:
            if item.name==teac_name:
                teacher_ob=item
                index=teacher_data.index(item)
        return teacher_ob,index
    
    
    
    
    def teacher_name():
        """
        生成教师名字列表函数
        :return: 返回名字列表
        """
        manage_data=data_read()
        teacher_list=[]
        for teacher in manage_data:
            teacher_list.append(teacher.name)
        # print(teacher_list)
        return teacher_list
    
    def subject_name():
        """
        生成课程名称列表函数
        :return: 课程名称列表
        """
        subject_data=subject_data_read()
        subject_list=[]
        for subject in subject_data:
            subject_list.append(subject.classes)
        # print(subject_list)
        return subject_list
    
    @check_login
    def creat_teacher():
        """
        创建教师函数
        :return:
        """
        #读取教书数据
        manage_data=data_read()
        teacher_list=teacher_name()
        name=input('输入教师姓名:')
        if name in teacher_list:    #判断是否已存在此教师
            print('已有教师:%s的数据'%name)
        else:
            while True:
                age=input('请输入教师年龄:')
                if age.isdigit():
                    age=int(age)
                    break
                else:print('输入有误,请重新输入')
            favor=input('请输入教师爱好和擅长,可多选,使用逗号隔开:')
            #调用教师类创建教师,并赋予相应属性
            docor_name=Teacher(name,age,favor)
            manage_data.append(docor_name)
            data_flush(manage_data)
            print('教师%s已创建成功!'%name)
    
    @check_login
    def creat_subject():
        """
        创建课程函数
        :return:
        """
        #读取课程数据
        subject_data=subject_data_read()
        subject_list=subject_name()
        classes=input('请输入课程名称:')       #判断是否有此课程
        if classes in subject_list:
            print('已经有%s课程'%classes)
        else:
            while True:
                value=input('请输入课时费:')
                if value.isdigit():
                    value=int(value)
                    break
                else:print('输入有误,请重新输入.')
            while True:
                print('请选择授课老师'.center(50,'*'))
                manage_data=show_teachers()
                num=input('请选择老师对应的序列号')
                if num.isdigit():
                    num=int(num)
                    if num < len(manage_data):
                        teacher_name=manage_data[num].name
                        #调用课程类创建课程,并赋予相应属性
                        subject_obj=Subject(classes,value,teacher_name)
                        subject_data.append(subject_obj)
                        subject_data_flush(subject_data)
                        break
                    else:print('输入有误,请重新输入.')
                else:print('输入有误,请重新输入.')
    
    # @check_login
    def show_teachers():
        """
        显示所有教师信息函数
        :return:
        """
        #遍历教师数据文件,并打印对应信息
        manage_data=data_read()
        row=prettytable.PrettyTable()
        row.field_names=['序列号','教师姓名','年龄','爱好','目前资产']
        for teach in manage_data:
            row.add_row([manage_data.index(teach),
                                              teach.name,
                                              teach.age,
                                              teach.favor,
                                              teach.asset])
        print(row)
        return manage_data
    
    def show_subject():
        """
        显示所有课程信息
        :return:
        """
        #遍历课程数据,并显示相应信息
        subject_data=subject_data_read()
        row=prettytable.PrettyTable()
        row.field_names=['序列号','学科名','课时费','授课老师',]
        for subject in subject_data:
            row.add_row([subject_data.index(subject),
                         subject.classes,
                         subject.value,
                         subject.teacher_name])
        print(row)
        return subject_data
    
    
    def logout():
        """
        退出系统函数
        :return:
        """
        exit('程序退出!')
    
    def menu():
        """
        打印菜单函数
        :return:
        """
        row=prettytable.PrettyTable()
        row.field_names=['创建老师','创建课程','查看所有老师','查看所有课程','退出程序']
        row.add_row([0,1,2,3,'q&quit'])
        print(row)
    
    def login():
        """
        登录函数
        :return:
        """
        user=input('请输入管理员用户名:')
        pwd=input('请输入密码:')
        if (user and pwd) == 'admin':
            #登录成功后修改全局变量
            global LOGIN_STATE
            LOGIN_STATE=True
            print('登录成功!')
            return LOGIN_STATE
        else:
            print('用户名或者密码错误!')
            return False
    
    @check_login
    def main():
        """
        主函数,系统入口
        :return:
        """
        while True:
            menu()
            #打印菜单后,将函数名形成列表让用户选择,选择后执行对应的函数
            menu_list=[creat_teacher,creat_subject,show_teachers,show_subject,logout]
            inp=input('请选择操作对应的序列号:')
            if inp.isdigit():
                inp=int(inp)
                if inp < len(menu_list):
                    menu_list[inp]()
                    time.sleep(1)
            elif inp == 'q' or inp =='quit':
                logout()
            else:print('输入错误,请重新输入.')
    

    core/student.py:

    #!/usr/bin/env python
    # -*-coding=utf-8-*-
    # Auther:ccorz Mail:ccniubi@163.com Blog:http://www.cnblogs.com/ccorz/
    # GitHub:https://github.com/ccorzorz
    
    import sys,os,pickle,prettytable
    BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(BASE_DIR)
    from conf.setting import *
    from core import manage_sys
    
    
    # USER=None
    
    def student_data_read():
        """
        读取学生数据
        :return: 读取到的学生数据
        """
        student_data=pickle.load(open(student_data_file,'rb'))
        return student_data
    
    def student_data_flush(args):
        """
        刷新学生数据
        :param args: 新的学生数据
        :return:
        """
        pickle.dump(args,open(student_data_file,'wb'))
    
    
    def student_name():
        """
        生成学生登录用户名列表
        :return:
        """
        student_data=student_data_read()
        student_name_list=[]
        for item in student_data:
            student_name_list.append(item.name)
        return student_name_list
    
    
    
    def regist():
        """
        注册函数
        :return:
        """
        student_data=student_data_read()
        student_name_list=student_name()
        name=input('请输入您的用户名:')
        if name in student_name_list:       #判断是否存在用户名
            print('已有用户:%s'%name)
        else:
            pwd=input('请输入您的密码:')
            for i in range(3):
                pwd_again=input('确认注册密码:')
                if pwd_again == pwd:
                    print('%s注册成功!'%name)
                    #调用学生类生成学生对象,并写入学生类数据库中
                    student_obj=Student(name,pwd)
                    student_data.append(student_obj)
                    student_data_flush(student_data)
                    break
                else:
                    print('密码不正确,请重新输入,还剩尝试次数%s'%(2-i))
    
    def s_login():
        """
        学生登录函数
        :return:
        """
        #读取学生类数据库和学生姓名列表,两个列表的下标相匹配
        student_data=student_data_read()
        student_name_list=student_name()
        name=input('请输入您的用户名:')
        if name not in student_name_list:
            print('无%s用户名.'%name)
        else:
            for i in range(3):
                pwd=input('请输入用户%s的密码:'%name)
                #如果输入的密码与学生类中的密码匹配
                if pwd==student_data[student_name_list.index(name)].pwd:
                    global USER
                    USER=name
                    print('登录成功!!!')
                    return True
                else:print('密码校验失败,剩余尝试次数:%s'%(2-i))
    
    
    def choice_subject():
        """
        选择课程函数
        :return:
        """
        #读取学生类数据库和学生姓名列表,两个列表的下标相匹配
        student_data=student_data_read()
        student_name_list=student_name()
        #读取课程类数据库
        subject_data=manage_sys.show_subject()
        inp = input('请选择学科名对应的序列号')
        if inp.isdigit():
            inp=int(inp)
            if inp < len(subject_data):
                #如果输入序列符合条件,课程数据库中取到相应课程对象
                subject=subject_data[inp]
                #学生类对象中取到课程列表,如果已有课程提示,如果无相同课程,添加入课程列表,并写入数据
                student_subject_list=student_data[student_name_list.index(USER)].subject_classes
                if subject.classes in student_subject_list:
                    print('您的课表中已有%s学科!'%subject.classes)
                else:
                    student_subject_list.append(subject.classes)
                    student_data_flush(student_data)
                    print('课程关联成功')
            else:print('选择有误,请重新输入')
        else:print('选择有误,请重新输入')
    
    
    def has_subject():
        """
        显示已选课程函数
        :return:
        """
        #读取学生类数据库和学生姓名列表,两个列表的下标相匹配
        student_data=student_data_read()
        student_name_list=student_name()
        #读取学生对象中的对应课程列表信息,打印所有课程信息
        student_subject_list=student_data[student_name_list.index(USER)].subject_classes
        row=prettytable.PrettyTable()
        row.field_names=['序列号','课程名']
        for item in student_subject_list:
            row.add_row([student_subject_list.index(item),item])
        print(row)
        return student_subject_list
    
    def s_logout():
        sys.exit('程序退出!')
    
    def show_menu():
        """
        登录后的菜单信息函数
        :return:
        """
        row=prettytable.PrettyTable()
        row.field_names=['选择课程','查看已选课程','上课','教学事故','退出程序']
        row.add_row([0,1,2,3,'3&q&quit'])
        print(row)
    
    def attend():
        """
        上课函数
        :return:
        """
        #读取学生类数据库和学生姓名列表,两个列表的下标相匹配
        student_data=student_data_read()
        student_name_list=student_name()
        student_subject_list=student_data[student_name_list.index(USER)].subject_classes
        for index,item in enumerate(student_subject_list):
            print(index,item)
        inp=input('请选择课程对应的序列号:')   #选择上课的目标课程
        if inp.isdigit():
            inp=int(inp)
            if inp < len(student_subject_list):     #如果符合序列号标准
                #确认课程名称
                subject_classes=student_subject_list[inp]
                #读取课程对象数据
                subject_data=manage_sys.subject_data_read()
                #确认相应的课程对象
                for item in subject_data:
                    if item.classes==subject_classes:
                        subject_obj=item
                #调用课程对象的上课方法
                subject_obj.attend_class()
            else:print('选择有误')
        else:print('选择有误!')
    
    def s_accidents():
        """
        教学事故函数,与上课函数相同
        :return:
        """
        student_data=student_data_read()
        student_name_list=student_name()
        student_subject_list=student_data[student_name_list.index(USER)].subject_classes
        for index,item in enumerate(student_subject_list):
            print(index,item)
        inp=input('请选择课程对应的序列号:')
        if inp.isdigit():
            inp=int(inp)
            if inp < len(student_subject_list):
                subject_classes=student_subject_list[inp]
                subject_data=manage_sys.subject_data_read()
                for item in subject_data:
                    if item.classes==subject_classes:
                        subject_obj=item
                #调用课程对象的教学事故方法
                subject_obj.accidents()
            else:print('选择有误')
        else:print('选择有误!')
    
    
    def main2():
        """
        登录后的菜单选择界面
        :return:
        """
        #将函数名形成列表,选择后执行函数
        menu=[choice_subject,has_subject,attend,s_accidents,s_logout]
        while True:
            show_menu()
            inp=input('请选择操作对应的序列号:')
            if inp == 'q' or inp == 'quit':
                s_logout()
            elif inp.isdigit():
                inp=int(inp)
                if inp < len(menu):
                    menu[inp]()
                else:print('输入有误,请重新输入')
            else:print('输入有误,请重新输入~')
    
    
    
    def main():
        """
        主函数入口
        :return:
        """
        print('''1.登录
    2.注册''')
        inp=input('请选择相应操作序列号:')
        if inp == '1':
            res=s_login()
            if res:
                main2()
        elif inp=='2':
            regist()
        else:print('选择有误!系统退出')
    
    
    # if __name__ == '__main__':
    #     main()
    

    data目录都是数据库文件,直接手动创建即可.收工!

  • 相关阅读:
    cae when分组统计
    查看 Chrome 下载的文件的真实下载地址
    directory opus使用教程
    文件内容极速搜索工具: silversearcher-ag
    LINUX SHELL 变量的二次引用
    JS小练习
    jQuery
    JS-BOM对象
    JS-DOM对象
    JavaScript-基础知识
  • 原文地址:https://www.cnblogs.com/ccorz/p/5613515.html
Copyright © 2011-2022 走看看