環境: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()
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])
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("輸入錯誤!")
#!/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
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()