Day7作业:选课系统

Posted ccorz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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目录都是数据库文件,直接手动创建即可.收工!

 

以上是关于Day7作业:选课系统的主要内容,如果未能解决你的问题,请参考以下文章

选课系统作业

python之路34面向对象作业之学生选课系统

Python作业-选课系统

选课系统作业

作业 选课系统

第六周作业——选课系统