學生信息管理系統
剛寫完趁熱打鐵寫個博客記錄一下,初學很多東西不懂,也可能有錯誤的地方,僅是做個記錄。2020.6.19
之前寫了一部分2020.5.9然後做了別的事情
1 數據庫
1.1 用戶信息(pickle)
- pickle的使用
- 用戶信息存儲用到了pickle模板,在登錄時輸入用戶名和密碼(均不能爲空),從本地字典獲取用戶信息,判斷用戶名和密碼是否匹配,如果匹配進入學生信息管理界面,如果匹配且僅是密碼錯誤則重新輸入密碼,如果用戶名從未出現過,則提醒註冊。
- 異常處理,從本地字典獲取用戶信息,如果沒有則新建本地數據庫。
- 註冊彈出子窗口,進行註冊時,本地加載已有用戶信息,如果沒有則已有用戶信息爲空。檢查用戶名是否存在、密碼是否爲空、密碼前後是否一致,註冊信息沒有問題則將用戶名密碼寫入數據庫,註冊成功關閉註冊框。
1.2 學生信息數據庫創建(sqlite3)
- 用到了sqlite數據庫,std_data.py文件爲用於數據庫創建的文件,創建數據庫名爲std_data.db,創建成功後創建student表,有七項:id,name,sex,age,job,std_id,tel,其中主鍵id自增,然後插入數據。
- 以下是創建數據庫名爲std_data.db,創建表,表名爲student
- 數據庫的創建參考教程
- 增刪查改
import sqlite3
conn=sqlite3.connect("std_data.db")#打開或創建數據庫
c=conn.cursor() #獲取遊標
sql='''
CREATE TABLE student
(id INTEGER PRIMARY KEY ,
name MESSAGE_TEXT ,
sex MESSAGE_TEXT ,
age NUMERIC ,
job MESSAGE_TEXT ,
std_id MESSAGE_TEXT ,
tel MESSAGE_TEXT );
'''
c.execute(sql) #執行sql語句
conn.commit() #提交數據庫操作
conn.close()
print("ok")
- 接下來插入數據
import sqlite3
conn=sqlite3.connect("std_data.db")#打開或創建數據庫
c=conn.cursor() #獲取遊標
sql1='''
insert into student (name, sex, age, job, std_id, tel)
values('張三','女',32,'大數據',123456,123456)
'''
sql2='''
insert into student (name, sex, age, job, std_id, tel)
values('李四','男',32,'物聯網',789456,789465)
'''
c.execute(sql1) #執行sql語句
c.execute(sql2)
conn.commit() #提交數據庫操作
conn.close()
2 界面設計
2.1 登錄界面
- 登陸界面窗口大小爲300*180;標題爲登錄;兩行內容:用戶名和密碼;兩個按鈕:登錄和退出;佈局用到了grid佈局,username爲用戶輸入的用戶名,password爲用戶輸入的密碼;用tkinter.Label().grid(),tkinter.Entry().grid(),tkinter.Button().grid()放置文字,輸入框和按鈕,用tkinter.messagebox.showerror(title, message)顯示彈窗。
- 如下爲登錄界面,本地已經存儲用戶名123,密碼123,可直接登錄;或隨意輸入用戶名和密碼,會自動提醒註冊。
- 代碼如下:
import tkinter.messagebox
from SignUp import *
from Manage import *
class Loginpage(object):
def __init__(self, master=None):
self.root = master
self.root.geometry('%dx%d' % (300, 180))
self.root.title('登錄')
self.username = tkinter.StringVar()
self.password = tkinter.StringVar()
self.createPage()
def createPage(self):
self.page = tkinter.Frame(self.root)
self.page.pack()
tkinter.Label(self.page).grid(row=0, stick='W')
tkinter.Label(self.page, text='賬戶: ').grid(row=1, stick='W', pady=10)
tkinter.Entry(self.page, textvariable=self.username).grid(row=1, column=1, stick='E')
tkinter.Label(self.page, text='密碼: ').grid(row=2, stick='W', pady=10)
tkinter.Entry(self.page, textvariable=self.password, show='*').grid(row=2, column=1, stick='E')
tkinter.Button(self.page, text='登陸', command=self.loginCheck).grid(row=3, stick='W', pady=10)
tkinter.Button(self.page, text='退出', command=self.page.quit).grid(row=3, column=1, stick='E')
def loginCheck(self):
name = self.username.get()
secret = self.password.get()
try:
with open('usr_info.pickle', 'rb') as usr_file:
usrs_info = pickle.load(usr_file)
except FileNotFoundError:
with open('usr_info.pickle', 'wb') as usr_file:
usrs_info = {'admin': 'admin'}
pickle.dump(usrs_info, usr_file)
if name in usrs_info:
if secret == usrs_info[name]:
tkinter.messagebox.showinfo(title='welcome', message='歡迎您:' + name)
for widget in self.page.winfo_children():
widget.destroy()
usr_file.close()
self.page.destroy()
Manage_student(self.root)
else:
tkinter.messagebox.showerror(message='密碼錯誤')
elif name == '' or secret == '':
tkinter.messagebox.showerror(message='用戶名或密碼爲空')
else:
is_signup = tkinter.messagebox.askyesno('歡迎', '您還沒有註冊,是否現在註冊')
if is_signup:
Signuppage(self.root)
2.2 註冊界面
- 用tkinter.Toplevel(root)創建子窗口,子窗口大小爲350*200;子窗口名爲註冊;三行內容:用戶名、密碼和再次輸入密碼;一個按鈕:確認註冊按鈕;用tkinter.Label().place(),tkinter.Entry().place(),tkinter.Button().place()放置文字,輸入框和按鈕,用tkinter.messagebox.showerror(title, message)顯示彈窗。
- new_name爲用戶輸入的用戶名,new_pwd爲用戶輸入的祕密,new_pwd_confirm爲用戶輸入的再次確認祕密,註冊信息沒有問題則將用戶名密碼寫入數據庫。
- 代碼如下:
import tkinter
import tkinter.messagebox
import pickle
def Signuppage(root):
def signtowcg():
nn = new_name.get()
np = new_pwd.get()
npf = new_pwd_confirm.get()
try:
with open('usr_info.pickle', 'rb') as usr_file:
exist_usr_info = pickle.load(usr_file)
except FileNotFoundError:
exist_usr_info = {}
if nn in exist_usr_info:
tkinter.messagebox.showerror('錯誤', '用戶名已存在')
elif np == '' or nn == '':
tkinter.messagebox.showerror('錯誤', '用戶名或密碼爲空')
elif np != npf:
tkinter.messagebox.showerror('錯誤', '密碼前後不一致')
else:
exist_usr_info[nn] = np
with open('usr_info.pickle', 'wb') as usr_file:
pickle.dump(exist_usr_info, usr_file)
tkinter.messagebox.showinfo('歡迎', '註冊成功')
window_sign_up.destroy()
window_sign_up = tkinter.Toplevel(root)
window_sign_up.geometry('350x200')
window_sign_up.title('註冊')
new_name = tkinter.StringVar()
tkinter.Label(window_sign_up, text='用戶名:').place(x=10, y=10)
tkinter.Entry(window_sign_up, textvariable=new_name).place(x=150, y=10)
new_pwd = tkinter.StringVar()
tkinter.Label(window_sign_up, text='請輸入密碼:').place(x=10, y=50)
tkinter.Entry(window_sign_up, textvariable=new_pwd, show='*').place(x=150, y=50)
new_pwd_confirm = tkinter.StringVar()
tkinter.Label(window_sign_up, text='請再次輸入密碼:').place(x=10, y=90)
tkinter.Entry(window_sign_up, textvariable=new_pwd_confirm, show='*').place(x=150, y=90)
tkinter.Button(window_sign_up, text='確認註冊', command=signtowcg).place(x=150, y=130)
2.3 學生信息管理界面
- 學生信息管理界面,標題爲學生管理系統,通過設定root.resizable(False, False)使得窗口大小不能改變,用tkinter.Label().place(),tkinter.Entry().place(),tkinter.Button().place()放置文字,輸入框和按鈕,用tkinter.messagebox.showerror(title, message)顯示彈窗。
- 在窗口上放置用來顯示學生信息的表格,使用Treeview組件實現,滾動條位於右側,設置了六列,顯示學生信息分別是:姓名、性別、年齡、專業、學號、電話,最後將Treeview組件與垂直滾動條結合,定義Treeview組件的左鍵單擊事件,並綁定到Treeview組件上,單擊鼠標左鍵,設置變量nameToDelete的值,然後可以使用“刪除”按鈕來刪除。
3 數據處理
- 設定doSql函數進行基本的數據庫操作,傳入sql語句即可執行。
- 在查找和修改中都用到了id,但是無法確定id的值,所以依據name,在數據庫中匹配。
3.1 查找
- 通過輸入姓名的查找方式,name = entry_name.get().strip(),name爲獲取姓名輸入框內容,name爲空,則不能進行查找,如果不爲空,打開std_data數據庫,執行sql語句select id,name,sex,age,job,std_id,tel from student,進行查詢,如果姓名匹配,則講查詢結果返回到輸入框,即在輸入框顯示查詢到的內容,最後關閉數據庫。
name = entry_name.get().strip()
if name == '':
tkinter.messagebox.showerror(title='很抱歉', message='查詢時名字不能爲空')
return
conn = sqlite3.connect("std_data.db")
c = conn.cursor()
sql1 = '''
SELECT id,name,sex,age,job,std_id,tel FROM student
'''
cursor = c.execute(sql1)
for row in cursor:
if row[1] == name:
entry_name.set(row[1])
comboSex.set(row[2])
entry_age.set(row[3])
entry_job.set(row[4])
entry_stdid.set(row[5])
entry_tel.set(row[6])
conn.close()
3.2 增加
- 獲取輸入框的所有內容進行添加信息。對信息進行檢查,輸入的姓名不能爲空且不能與數據庫中已有信息姓名重複,SELECT COUNT(id) FROM student WHERE name="’ + name + '",執行語句記錄數據庫中name出現的次數,用於判斷姓名是否重複;對輸入的年齡信息進行檢查,年齡必須爲數字且在1~100之間;檢查輸入的專業不能爲空;檢查輸入的學號不能爲空且必須爲數字;檢查輸入的電話不能爲空且必須爲數字。所有信息都檢查通過的話,插入數據庫,執行語句INSERT INTO student() VALUES(),更新信息並且把顯示的信息表更新。
def buttonAddClick():
name = entry_name.get().strip()
if name == '':
tkinter.messagebox.showerror(title='很抱歉', message='必須輸入姓名')
return
conn = sqlite3.connect('std_data.db')
cur = conn.cursor()
cur.execute('SELECT COUNT(id) FROM student WHERE name="' + name + '"')
c = cur.fetchone()[0]
conn.close()
if c != 0:
tkinter.messagebox.showerror(title='很抱歉', message='姓名不能重複')
return
sex = comboSex.get()
age = entry_age.get().strip()
if not age.isdigit():
tkinter.messagebox.showerror(title='很抱歉', message='年齡必須爲數字')
return
if not 1 < int(age) < 100:
tkinter.messagebox.showerror(title='很抱歉', message='年齡必須在1到100之間')
return
department = entry_job.get().strip()
if department == '':
tkinter.messagebox.showerror(title='很抱歉', message='必須輸入專業')
return
std_id = entry_stdid.get().strip()
if std_id == '' or (not std_id.isdigit()):
tkinter.messagebox.showerror(title='很抱歉', message='學號必須是數字')
return
telephone = entry_tel.get().strip()
if telephone == '' or (not telephone.isdigit()):
tkinter.messagebox.showerror(title='很抱歉', message='電話號碼必須是數字')
return
sql = 'INSERT INTO student(name,sex,age,job,std_id,tel) VALUES("'
sql += name + '","' + sex + '",' + age + ',"' + department + '","'
sql += std_id + '","' + telephone + '")'
doSql(sql)
bindData()
3.3 刪除
- 通過點擊信息表姓名獲取需要刪除的姓名,姓名不可以爲空,選中後執行sql語句DELETE FROM student where name="’ + name + ‘",顯示彈窗刪除成功,更新信息並且把顯示的信息表更新,nameToDelete.set(’’)重置爲空。
def buttonDeleteClick():
name = nameToDelete.get()
if name == '':
tkinter.messagebox.showerror(title='很抱歉', message='請選擇一條記錄')
return
sql = 'DELETE FROM student WHERE name="' + name + '"'
doSql(sql)
tkinter.messagebox.showinfo('恭喜', '刪除成功')
nameToDelete.set('')
bindData()
3.4 修改
- 修改信息只有姓名不可以修改,除姓名外的修改信息填入對應的輸入框,點擊修改即可修改。re_sex、re_age、re_job、re_stdid、re_tel分別對應修改的性別、年齡、工作、學號、電話,執行sql語句UPDATE student SET sex = ‘%s’ WHERE id = ‘%s’" %(re_sex, id_row),更新語句每句更改信息最多2處,所以每句只更改1處。
- 同增加項一樣進行信息檢查。
def buttonReviseClick():
name = entry_name.get().strip()
re_sex = comboSex.get().strip()
re_age = entry_age.get().strip()
re_job = entry_job.get().strip()
re_stdid = entry_stdid.get().strip()
re_tel = entry_tel.get().strip()
if name == '':
tkinter.messagebox.showerror(title='很抱歉', message='必須輸入姓名')
return
if not re_age.isdigit():
tkinter.messagebox.showerror(title='很抱歉', message='年齡必須爲數字')
return
if not 1 < int(re_age) < 100:
tkinter.messagebox.showerror(title='很抱歉', message='年齡必須在1到100之間')
return
if re_job == '':
tkinter.messagebox.showerror(title='很抱歉', message='必須輸入專業')
return
if re_stdid == '' or (not re_stdid.isdigit()):
tkinter.messagebox.showerror(title='很抱歉', message='學號必須是數字')
return
if re_tel == '' or (not re_tel.isdigit()):
tkinter.messagebox.showerror(title='很抱歉', message='電話號碼必須是數字')
return
conn = sqlite3.connect("std_data.db")
c = conn.cursor()
sql1 = '''
SELECT id,name,sex,age,job,std_id,tel FROM student
'''
cursor = c.execute(sql1)
for row in cursor:
if row[1] == name:
id_row = row[0]
if re_sex != row[2] :
c.execute("UPDATE student SET sex = '%s' WHERE id = '%s'"
%(re_sex, id_row))
if re_age != row[3] :
c.execute("UPDATE student SET age = '%s' WHERE id = '%s'"
% (re_age, id_row))
if re_job != row[4] :
c.execute("UPDATE student SET job = '%s' WHERE id = '%s'"
% (re_job, id_row))
if re_stdid != row[5] :
c.execute("UPDATE student SET std_id = '%s' WHERE id = '%s'"
% (re_stdid, id_row))
if re_tel != row[6] :
c.execute("UPDATE student SET tel = '%s' WHERE id = '%s'"
% (re_tel, id_row))
conn.commit()
conn.close()
tkinter.messagebox.showinfo('恭喜', '修改成功')
bindData()
4 心得
- 完成項目過程中,遇到困難在CSDN博客中都得到了解決。Tkinter模塊在課堂上講過,動手實踐後理解更加透徹。在這次學生信息管理系統設計的過程中,我熟練使用tkinter創建窗口,設置窗口標題,窗口大小等,學會grid佈局和通過place設置放置位置,在實現GUI中發揮很大作用。
- 課堂上講過數據庫的操作,實踐後理解更加深刻,自己創建了數據庫,創建過程在std_data.py文件中,增刪查改,INSERT INTO,DELETE,SELECT,UPDATE語句的使用。
- 很感謝老師提供的學生信息管理系統設計這一機會,有這麼一次實踐的經歷,感覺還是很不錯的。因爲我們不只是學到了python的基礎知識,還應該學會如何用模塊實現想要的結果,這提升了許多方面的能力。