學員管理系統

環境:windows或者Linux,python3.6,mysql5.7
要求:
用戶角色,講師\學員, 用戶登錄後根據角色不一樣,能作的事情不一樣,分別以下
講師視圖
  管理班級,可建立班級,根據學員qq號把學員加入班級
  可建立指定班級的上課紀錄,注意一節上課紀錄對應多條學員的上課紀錄, 即每節課都有整班學員上, 爲了紀錄每位學員的學習成績,需在建立每節上課紀錄是,同時 爲這個班的每位學員建立一條上課紀錄
  爲學員批改爲績, 一條一條的手動修改爲績
學員視圖
提交做業
查看做業成績
一個學員能夠同時屬於多個班級,就像報了Linux的同時也能夠報名Python同樣, 因此提交做業時需先選擇班級,再選擇具體上課的節數
附加:學員能夠查看本身的班級成績排名

項目結構:
rpc_client ---|
bin ---|
start.py ......啓動
conf---|
config.py ......配置參數
system.ini ......配置文件
core---|
entrance.py ......登陸認證的方法
main.py ......學生視圖,導師視圖
db ---|
mysqldb.py ......鏈接執行mysql

數據庫結構:
student:
id , name姓名 , password密碼 , qq

teacher:
id , name , password , qq

class:
id , class_name 班級名稱

class_record:
id , class_id , course_num 班級課程節數 # class_id與表class中的id字段作外鍵關聯

score:
id , class_record_id(class_record表中的id) , student_id(student表中的id) , socre(成績) , sign(做業提交標誌,0爲未提交,1爲提交)
# class_record_id與表class_record中的id字段作外鍵關聯,student_id與表student中的id字段作外鍵關聯

class_union_student (學生與班級多對多關聯表)
id , class_id , student_id
# student_id與表student中的id字段作外鍵關聯,class_id與表class中的id字段作外鍵關聯

用法:
啓動start.py
爲方便測試,自動註冊兩個學員和一個老師,學員1帳號,密碼,qq號爲 zh,123,123456,學員2爲zs,123,654321,老師帳號密碼:alex,123
qq號做爲加入班級是須要輸入的
老師視圖:
"建立班級":輸入班級名稱建立班級(在class中添加記錄)
"加入班級":輸入學員qq號加入班級(可添加多個,用,隔開)(在class_union_student中添加記錄)
"建立上課記錄":建立上課記錄,同時給學員建立學習記錄(class_record 中添加一條記錄,score中添加一條記錄)
"批改爲績":須要在學員提交了做業後纔可批改爲績(在score中修改score成績記錄)

學生視圖:
"提交做業":在建立了上課記錄後學員便可提交做業(在score中修改sign標誌)
"查當作績":在老師批改爲績後學員可查當作績
"查看班級排名":在老師批改爲績後學員可查看班級排名

輸入b返回上一級


bin:
#!/usr/bin/env python
# -*-coding:utf-8-*-
# Author:zh
import os
import sys
PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(PATH)
from core import entrance
from db import mysqldb

mysqldb.create_table()
mysqldb.test()  # 輔助註冊用戶,方便測試
entrance.run()
start.py

conf:python

#!/usr/bin/env python
# -*-coding:utf-8-*-
# _author_=zh
import os
import configparser
PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


class Configuration(object):
    def __init__(self):
        self.config = configparser.ConfigParser()
        self.name = PATH+os.sep+"conf"+os.sep+"system.ini"

    def init_config(self):
        # 初始化配置文件,ip :客戶端IP,port:客戶端端口
        if not os.path.exists(self.name):
            self.config["config"] = {"host": '192.168.200.128', "port": 3306, "user": 'root',
                                     "passwd": '123456', "db": 'mysql', "charset": 'utf8'}
            self.config.write(open(self.name, "w", encoding="utf-8", ))

    def get_config(self, head="config"):
        '''
        獲取配置文件數據
        :param head: 配置文件的section,默認取初始化文件config的數據
        :return:返回head中的全部數據(列表)
        '''
        self.init_config() # 取文件數據以前生成配置文件
        self.config.read(self.name, encoding="utf-8")
        if self.config.has_section(head):
            section = self.config.sections()
            return self.config.items(section[0])
config

core:mysql

#!/usr/bin/env python
# -*-coding:utf-8-*-
# Author:zh
import os
import sys
import hashlib
PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(PATH)
from db import mysqldb
from conf import config
from .import main


class Entrance(object):
    # 這個類用來提供註冊和登錄方法
    def __init__(self, enter):
        self.num = enter
        obj = config.Configuration()
        data = obj.get_config()
        self.sql_obj = mysqldb.SqlServer(data[0][1], data[1][1], data[2][1], data[3][1], data[4][1], data[5][1])

    def __del__(self):
        self.sql_obj.close()

    def load(self):
        # 登錄
        while True:
            user_name = input("name:")
            if user_name == "b":
                break
            pwd = input("password:")
            pwd_hash = hashlib.md5()
            pwd_hash.update(pwd.encode())
            pwd = pwd_hash.hexdigest()
            if self.num == "1":
                table_name = "student"
            elif self.num == "2":
                table_name = "teacher"
            sql_data = "select password from %s where name = '%s';" % (table_name, user_name)
            try:
                self.sql_obj.run(sql_data)
                answer = self.sql_obj.get()
                if answer == ():
                    print("沒有此用戶,請從新登錄")
                else:
                    if pwd == answer[0][0]:
                        return user_name
                        print("welcome")
                        break
                    else:
                        print("密碼錯誤!")
            except Exception as e1:
                print("輸入錯誤,錯誤:%s" % e1)

    def register(self):
        # 註冊
        while True:
            user_name = input("name:")
            if user_name == "b":
                break
            pwd = input("password:")
            pwd_hash = hashlib.md5()
            pwd_hash.update(pwd.encode())
            pwd = pwd_hash.hexdigest()
            qq = input("qq:")
            try:
                qq = int(qq)
            except ValueError:
                print("qq號格式不正確")
                continue
            if self.num == "1":
                table_name = "student"
            elif self.num == "2":
                table_name = "teacher"
            sql_data = "insert into %s (name,password,qq) values('%s','%s',%s);" % (table_name, user_name, pwd, qq)
            try:
                self.sql_obj.run(sql_data)
                self.sql_obj.commit()
                print("welcome")
                return user_name
            except Exception as e1:
                print("執行失敗,錯誤:%s" % e1)


def show(n):
    # 這個方法用來展現數據
    for count, i in enumerate(n):
        print("%s: %s" % (count+1, i))


def run():
    while True:
        info = ["學生", "老師"]
        show(info)
        choose = input("請選擇入口:")
        if choose == 'b':
            break
        if choose is "":
            continue
        if int(choose) in (1, len(info)):
            start_obj = Entrance(choose)
            while True:
                info = ["註冊", "登錄"]
                show(info)
                num = input("請選擇入口:")
                if num is "":
                    continue
                elif num == "1":
                    name = start_obj.register()
                    break
                elif num == "2":
                    name = start_obj.load()
                    break
                else:
                    print("輸入錯誤!")
                    continue
            if choose == "2":
                info = ["建立班級", "加入班級", "建立上課記錄", "批改爲績"]
                obj = main.TeacherView()
                data = {1: "create_class",
                        2: "join_class",
                        3: "class_record",
                        4: "alter_score"}
            elif choose == "1":
                info = ["提交做業", "查當作績", "查看班級排名"]
                obj = main.StudentView(name)
                data = {1: "submit",
                        2: "view",
                        3: "rank"}
            while True:
                show(info)
                choose = input("選擇操做:")
                if choose == 'b':
                    break
                if choose is "":
                    continue
                try:
                    choose = int(choose)
                except ValueError as e:
                    print("請輸入數字!錯誤:%s" % e)
                    continue
                if hasattr(obj, data[choose]):
                    func = getattr(obj, data[choose])
                    func()
                else:
                    print("類中無此方法,請查看!")
        else:
            print("輸入錯誤!")
entrance
#!/usr/bin/env python
# -*-coding:utf-8-*-
# Author:zh
import pymysql
from db import mysqldb
from conf import config


class TeacherView(object):
    # 這個類用來處理講師視圖
    def __init__(self):
        obj = config.Configuration()
        data = obj.get_config()
        self.sql_obj = mysqldb.SqlServer(data[0][1], data[1][1], data[2][1], data[3][1], data[4][1], data[5][1])

    def __del__(self):
        self.sql_obj.close()

    def create_class(self):
        # 這個方法用來建立班級
        while True:
            class_name = input("請輸入班級名:")
            if class_name == "b":
                break
            sql_data = "insert into class (class_name) values('%s');" % class_name
            try:
                self.sql_obj.run(sql_data)
                self.sql_obj.commit()
                print("建立成功")
                break
            except pymysql.err.IntegrityError as e1:
                print("班級名已存在,錯誤:%s" % e1)
            except Exception as e1:
                print("錯誤:%s" % e1)

    def join_class(self):
        # 這個方法用來加入班級
        sign = True
        while sign:
            qq = input("請輸入qq號(多個用,隔開):")
            if qq == "b":
                break
            sql_data = "select id from student where qq in (%s)" % qq  # 查看全部qq號
            self.sql_obj.run(sql_data)
            id_tuple = self.sql_obj.get()
            if id_tuple == ():
                print("無使用該qq的學員")
                continue
            class_name = show_class(self.sql_obj)
            if class_name is not None:
                count = 0
                for id in id_tuple:
                    sql_data = "insert into class_union_student(class_id,student_id) select (select id" \
                               " from class where class_name='%s') as class_id,%s from dual;" % (class_name, id[0])
                    try:
                        self.sql_obj.run(sql_data)
                        self.sql_obj.commit()
                        count += 1
                    except Exception as e1:
                        print("插入失敗,錯誤內容:%s" % e1)
                print("成功%s個" % count)
                sign = False

    def class_record(self):
        # 這個方法用來建立上課記錄
        class_name = show_class(self.sql_obj)
        if class_name is not None:
            sign = True
            while sign:
                class_num = input("請輸入上課節數:")
                if class_num == "b":
                    break
                # 插入上課記錄
                sql_class_record = "insert into class_record(class_id,course_num) " \
                                   "select id,%s from class where class_name = '%s'" % (class_num, class_name)
                try:
                    self.sql_obj.run(sql_class_record)
                except Exception as e1:
                    print("插入上課記錄失敗,錯誤:%s" % e1)
                sql_score = "select student_id from class_union_student" \
                            " where class_id =(select id from class where class_name = '%s')" % class_name
                self.sql_obj.run(sql_score)
                student_tuple = self.sql_obj.get()
                for student_id in student_tuple:
                    # 給全部班級的學生添加上課記錄
                    sql_score = "insert into score(class_record_id,student_id) " \
                                "select(select id from class_record where class_id = " \
                                "(select id from class where class_name = '%s') and course_num = %s ) " \
                                "as class_record_id,%s from dual;" % (class_name, class_num, student_id[0])
                    try:
                        self.sql_obj.run(sql_score)
                    except Exception as e1:
                        print("上課記錄插入失敗,學生ID爲%s,錯誤內容%s" % (student_id[0], e1))
                self.sql_obj.commit()
                sign = False

    def alter_score(self):
        # 這個方法用來修改學員成績
        class_name = show_class(self.sql_obj)
        if class_name is not None:
            sql_student = "select name from student where id in " \
                          "(select student_id from class_union_student where class_id = " \
                          "(select id from class where class_name = '%s') " \
                          "union select student_id from score where sign = '1' )" % class_name
            self.sql_obj.run(sql_student)
            student_tuple = self.sql_obj.get()
            sign = True
            while sign:
                for count, i in enumerate(student_tuple):
                    print("%s: %s" % (count + 1, i[0]))
                num_student = input("請選擇須要修改爲績的學生:")
                if num_student == "b":
                    break
                if num_student is "":
                    continue
                if int(num_student) in (1, len(student_tuple)):
                    student_name = student_tuple[int(num_student)-1][0]
                    sql_score = "select '%s',b.course_num,a.score,a.id from score a " \
                                "join class_record b on a.class_record_id = b.id where a.sign = '1' and a.student_id=(" \
                                "select id from student where name = '%s')" % (class_name, student_name)
                    self.sql_obj.run(sql_score)
                    student_score = self.sql_obj.get()
                    if student_score is ():
                        print("沒有須要批改的做業")
                        continue
                    else:
                        count = 0
                        for i in student_score:
                            count += 1
                            print("%s: 班級:%s,節數:%s,成績:%s" % (count, i[0], i[1], i[2]))
                    while sign:
                        enter = input("請選擇須要修改的成績:")
                        if enter == "b":
                            break
                        try:
                            enter = int(enter)
                        except ValueError as e1:
                            print("輸入錯誤:%s" % e1)
                            continue
                        if enter is "":
                            continue
                        if enter in range(1, len(student_score) + 1):
                            score_id = student_score[enter-1][3]
                            while sign:
                                change_score = input("請輸入修改的成績:")
                                if change_score == "b":
                                    break
                                try:
                                    change_score = int(change_score)
                                except ValueError as e1:
                                    print("error:%s,請輸入數字" % e1)
                                    continue
                                sql_change = "update score set score = %s where id = %s" % (change_score, score_id)
                                try:
                                    self.sql_obj.run(sql_change)
                                    self.sql_obj.commit()
                                    print("修改爲功")
                                except Exception as e1:
                                    print("更新失敗,name爲:%s,class爲:%s,錯誤內容:%s" % (student_name, class_name, e1))
                                sign = False
                        else:
                            print("輸入錯誤")
                else:
                    print("輸入錯誤")


class StudentView(object):
    # 這個類用來處理學生視圖
    def __init__(self, user_name):
        # user_name:傳入登錄人姓名
        self.name = user_name
        obj = config.Configuration()
        data = obj.get_config()
        self.sql_obj = mysqldb.SqlServer(data[0][1], data[1][1], data[2][1], data[3][1], data[4][1], data[5][1])

    def __del__(self):
        self.sql_obj.close()

    def submit(self):
        # 這個方法用來提交做業
        class_name = show_class(self.sql_obj)
        if class_name is not None:
            sql_num = "select id,'%s',course_num from class_record where class_id = " \
                      "(select id from class where class_name = '%s')" % (class_name, class_name)
            self.sql_obj.run(sql_num)
            course_num_tuple = self.sql_obj.get()
            if course_num_tuple is ():
                print("未創建上課記錄")
            else:
                count = 0
                for course_num in course_num_tuple:
                    count += 1
                    print("%s: 班級:%s,節數:%s" % (count, class_name, course_num[2]))
                sign = True
                while sign:
                    class_num = input("請選擇上課節數:")
                    if class_num is "":
                        continue
                    try:
                        class_num = int(class_num)
                    except ValueError as e1:
                        print("error:%s,請輸入數字" % e1)
                        continue
                    if class_num in range(1, len(course_num_tuple) + 1):
                        sql_score = "update score set sign = '1' where class_record_id = %s and student_id =" \
                                    "(select id from student where name = '%s')" \
                                    % (course_num_tuple[class_num-1][0], self.name)
                        try:
                            self.sql_obj.run(sql_score)
                            self.sql_obj.commit()
                            print("提交成功!")
                        except Exception as e1:
                            print("更新失敗,name爲:%s,class爲:%s,上課節數爲:%s,錯誤內容:%s" % (self.name, class_name, class_num, e1))
                        sign = False

    def view(self):
        # 這個方法用來查當作績
        class_name = show_class(self.sql_obj)
        if class_name is not None:
            sql_score = "select '%s',a.course_num,b.score,b.sign from class_record a join score b " \
                        "on b.class_record_id = a.id where b.student_id= (select id from student where name = '%s')" \
                        % (class_name, self.name)
            self.sql_obj.run(sql_score)
            score_tuple = self.sql_obj.get()
            for score in score_tuple:
                print("班級:%s,節數:%s,成績:%s,是否提交:%s" % (score[0], score[1], score[2], score[3]))

    def rank(self):
        # 這個方法用來查看班級排名
        class_name = show_class(self.sql_obj)
        if class_name is not None:
            sql_rank = "select sum(score) a,student_id from score where class_record_id in " \
                       "(select id from class_record where class_id = " \
                       "(select id from class where class_name = '%s')) group by student_id order by a desc" % class_name
            self.sql_obj.run(sql_rank)
            rank_tuple = self.sql_obj.get()
            sql_score = "select sum(score) from score where student_id = " \
                        "(select id from student where name = '%s') and class_record_id  in" \
                        "(select id from class_record where class_id = " \
                        "(select id from class where class_name = '%s'))" % (self.name, class_name)
            self.sql_obj.run(sql_score)
            my_score_tuple = self.sql_obj.get()
            if my_score_tuple[0][0] is not None:
                for index, i in enumerate(rank_tuple):
                    if my_score_tuple[0][0] == i[0]:
                        print("第%s名" % str(index+1))
            else:
                print("沒有成績")


def show_class(class_obj):
    # 這個方法用來格式化顯示班級
    # class_obj:數據庫鏈接
    sql_data = "select class_name from class;"
    class_obj.run(sql_data)
    answer = class_obj.get()
    if answer == ():
        print("請先創建班級")
        class_name = None
    else:
        for count, i in enumerate(answer):
            print("%s: %s" % (count + 1, i[0]))
        while True:
            enter = input("請選擇班級:")
            try:
                enter = int(enter)
            except ValueError as e1:
                print("輸入錯誤:%s" % e1)
                continue
            if enter is "":
                continue
            if enter in range(1, len(answer)+1):
                class_name = answer[enter - 1][0]
                break
            else:
                print("輸入錯誤")
    return class_name
main

db:sql

#!/usr/bin/env python
# -*-coding:utf-8-*-
# Author:zh
import pymysql
import os
import sys
PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(PATH)
from conf import config


class SqlServer(object):
    def __init__(self, host, port, user, passwd, db, charset):
        self.host = host
        self.port = port
        self.user = user
        self.passwd = passwd
        self.db = db
        self.charset = charset
        self.conn = pymysql.connect(host=self.host, port=int(self.port),
                                    user=self.user, passwd=self.passwd, db=self.db, charset=self.charset)
        self.cursor = self.conn.cursor()

    def run(self, sql):
        self.cursor.execute(sql)

    def get(self):
        answer = self.cursor.fetchall()
        return answer

    def commit(self):
        self.conn.commit()

    def close(self):
        self.cursor.close()
        self.conn.close()


table_data = [
    "create table class("
    "id int auto_increment primary key,"
    "class_name varchar(20) not null unique)",

    "create table student(id int auto_increment primary key,"
    "name varchar(20) not NULL unique,"
    "password varchar(32) not NULL,"
    "qq varchar(20) UNIQUE not NULL)",

    "create table teacher(id int auto_increment primary key,"
    "name varchar(20) not NULL unique,"
    "password varchar(32) not NULL,"
    "qq varchar(20) UNIQUE not NULL)",

    "create table class_record("
    "id int auto_increment primary key,"
    "class_id INT not NULL ,"
    "course_num INT not NULL,"
    "UNIQUE key u_class_record (class_id ,course_num),"
    "foreign key f_class_record (class_id) references class(id) on delete cascade on update cascade)",

    "create table score("
    "id int auto_increment primary key,"
    "class_record_id INT not NULL,"
    "student_id INT not NULL,"
    "score INT DEFAULT NULL ,"
    "sign Enum('0','1') DEFAULT '0',"
    "UNIQUE key u_score (class_record_id ,student_id ),"
    "foreign key f_score_1 (class_record_id) references class_record(id) on delete cascade on update cascade,"
    "foreign key f_score_2 (student_id) references student(id) on delete cascade on update cascade)",

    "create table class_union_student("
    "id int auto_increment primary key,"
    "class_id INT not NULL,"
    "student_id INT not NULL,"
    "UNIQUE key u_class_union_student (class_id ,student_id ),"
    "foreign key f1_class_union_student (class_id) references class(id) on delete cascade on update cascade,"
    "foreign key f2_class_union_student (student_id) references student(id) on delete cascade on update cascade)"
    ]


def create_table():
    obj = config.Configuration()
    data = obj.get_config()
    sql_obj = SqlServer(data[0][1], data[1][1], data[2][1], data[3][1], data[4][1], data[5][1])
    sql_conn = "select table_name from information_schema.tables " \
               "where table_schema= '%s' and table_name = 'class_union_student'" % data[4][1]
    sql_obj.run(sql_conn)
    table = sql_obj.get()
    if table == ():
        for j in table_data:
            sql_obj.run(j)
    sql_obj.close()


def test():
    obj = config.Configuration()
    data = obj.get_config()
    sql_obj = SqlServer(data[0][1], data[1][1], data[2][1], data[3][1], data[4][1], data[5][1])
    sql_conn = "select * from student;"
    sql_obj.run(sql_conn)
    answer = sql_obj.get()
    if answer == ():
        sql_list = ["insert into student(name,password,qq) values('zs','202cb962ac59075b964b07152d234b70','123456')",
                    "insert into student(name,password,qq) values('zh','202cb962ac59075b964b07152d234b70','654321')",
                    "insert into teacher(name,password,qq) values('alex','202cb962ac59075b964b07152d234b70','987654')"]
        for i in sql_list:
            sql_obj.run(i)
            sql_obj.commit()
    sql_obj.close()
mysqldb
相關文章
相關標籤/搜索