Python面向?qū)ο髮?shí)戰(zhàn):學(xué)生教師信息管理(5)

前言

這一節(jié)我們將實(shí)現(xiàn)校驗(yàn)、添加、修改、刪除、保存的功能。

part5 完成項(xiàng)目

一、創(chuàng)建StudentServicel類

1. 準(zhǔn)備好校驗(yàn)類check

為了完善學(xué)生或教師信息的添加功能,我們需要對(duì)輸入的數(shù)據(jù)進(jìn)行校驗(yàn)。前面我們已經(jīng)使用過(guò)Check類,利用正則表達(dá)式分別對(duì)學(xué)號(hào)、姓名、性別、手機(jī)號(hào)、郵箱的基本規(guī)范做校驗(yàn)?,F(xiàn)在我們可以直接拿來(lái)使用。

2. 定義抽象類services

我們?cè)俣x一個(gè)抽象類services,準(zhǔn)備定義抽象方法有:add
、update、delete、check;

from abc import *
class Services(metaclass=ABCMeta):
    @abstractmethod
    def add(self): pass
    @abstractmethod
    def update(self): pass
    @abstractmethod
    def delete(self): pass    
    @abstractmethod
    def check(self): pass

之后,我們?cè)趯?shí)現(xiàn)學(xué)生操作的功能創(chuàng)建一個(gè)studentservice模塊,繼承Services和Check。

class StudentServices(Services, Check):
    def __init__(self, list_all, student_current: Student):
        Services.__init__(self)
        Check.__init__(self)
        self.list_all = list_all
        self.student_current = student_current

二、對(duì)輸入的數(shù)據(jù)數(shù)據(jù)進(jìn)行校驗(yàn)

開發(fā)到這個(gè)階段,在主界面點(diǎn)擊添加按鈕的時(shí)候,如果系統(tǒng)報(bào)錯(cuò)。可能是我們的StudentDetail類的構(gòu)造函數(shù)第二個(gè)參數(shù)current_student沒有設(shè)置默認(rèn)值,我們只需要給其添加一個(gè)默認(rèn)值current_student=""即可。它即使沒有收到參數(shù)的傳遞它也不會(huì)報(bào)錯(cuò)了。

1. 實(shí)現(xiàn)校驗(yàn)功能

當(dāng)我們點(diǎn)擊添加按鈕打開明細(xì)窗體,填入數(shù)據(jù)的時(shí)候,點(diǎn)擊保存按鈕時(shí),此時(shí)應(yīng)當(dāng)觸發(fā)對(duì)所填入數(shù)據(jù)的校驗(yàn)。
由于我們的保存按鈕寫在了basedetail中,所以我們先定義一個(gè)commit函數(shù)。然后在studentdetail重寫commit方法。
之后我們?cè)?code>StudentService類中定義一個(gè)check方法,用來(lái)校驗(yàn)輸入的信息是否有效。由于性別是通過(guò)radiobutton獲取的無(wú)需校驗(yàn),這里我們只校驗(yàn)學(xué)號(hào)、姓名、電話、郵箱,并作出如下規(guī)定:

check的返回值 含義
1 符合要求
2 學(xué)號(hào)不符合要求
3 姓名不符合要求
4 電話不符合要求
5 郵箱地址不符合要求

我們定義校驗(yàn)函數(shù)如下:

def check(self):
    return_number = 0
    if not self.check_sno(self.student_current.sno):
        return_number = 2
    elif not self.check_name(self.student_current.name):
        return_number = 3
    elif not self.check_mobile(self.student_current.mobile):
        return_number = 4
    elif not self.check_email(self.student_current.email):
        return_number = 5
    else:
        return_number = 1
    return return_number

我們回到studentdetail模塊中,給commit函數(shù)添加功能,其中包括:封裝當(dāng)前填入的學(xué)生信息。
我們定義一個(gè)方法get_current_student把填入的信息封裝到student類

def get_current_student(self):
    sno = self.var_sno.get()
    name = self.var_name.get()
    gender = ""
    if self.var_gender.get() == 1:
        gender = "男"
    elif self.var_gender.get() == 2:
        gender = "女"
    birthday = self.var_birthday.get()
    mobile = self.var_mobile.get()
    email = self.var_email.get()
    profession = self.var_profession.get()
    entry_time = self.var_entry_time
    # 封裝
    current_student = Student(sno, gender, birthday, birthday, mobile, email, profession, entry_time)
    # 返回
    return current_student

然后在commit方法里,對(duì)封裝的學(xué)生對(duì)象調(diào)用check方法進(jìn)行校驗(yàn):

    # 【1】封裝當(dāng)前的學(xué)生
    current_student = self.get_current_student()
    current_studentservices = StudentServices(self.list_student_all, current_student)

    # 【2】校驗(yàn)學(xué)生
    return_number = current_studentservices.check()
    if return_number == 2:
        showinfo("系統(tǒng)消息", "學(xué)號(hào)不符合要求")
    elif return_number == 3:
        showinfo("系統(tǒng)消息", "姓名不符合要求")
    elif return_number == 4:
        showinfo("系統(tǒng)消息", "手機(jī)號(hào)碼不符合要求")
    elif return_number == 5:
        showinfo("系統(tǒng)消息", "郵箱地址不符合要求")
    elif return_number == 1:
        showinfo("系統(tǒng)消息", "所有都符合要求")

這里我們只對(duì)學(xué)號(hào)、姓名、手機(jī)號(hào)碼、郵箱進(jìn)行校驗(yàn),如果不滿足,就彈出警示框。


學(xué)號(hào)必須以95開頭5位數(shù)

三、添加學(xué)生信息

1. 需求分析

我們希望打開添加學(xué)生信息窗口后,填入學(xué)生信息,點(diǎn)擊保存按鈕后,數(shù)據(jù)會(huì)立即顯示在學(xué)校信息列表里。

2. 實(shí)現(xiàn)過(guò)程

為了獲取填入的信息,我們?cè)?code>studentservices中定義add方法,將student_current中的各個(gè)屬性依次添加到current_student_list列表中,再加current_student_list列表加入到總列表list_all中即可。

def add(self):
    """
    添加學(xué)生
    """
    # 暫存填入的學(xué)生信息
    current_student_list = []
    current_student_list.append(self.student_current.sno)
    current_student_list.append(self.student_current.name)
    current_student_list.append(self.student_current.gender)
    current_student_list.append(self.student_current.birthday)
    current_student_list.append(self.student_current.mobile)
    current_student_list.append(self.student_current.email)
    current_student_list.append(self.student_current.profession)
    current_student_list.append(self.student_current.entry_time)

    # 當(dāng)前學(xué)生添加到集合中
    self.list_all.append(current_student_list)

我們?cè)俚?code>studentdetail模塊中,將commit方法繼續(xù)完善,補(bǔ)充添加功能。

current_studentservices.add()

執(zhí)行add方法后,list_student_all總學(xué)生列表已經(jīng)發(fā)生了變化,在明細(xì)窗口當(dāng)我們點(diǎn)擊關(guān)閉的時(shí)候,我們要將變化體現(xiàn)到主窗口的表格中來(lái)。
在我們添加完成后定義一個(gè)反饋信號(hào)給主窗體,

self.userinfo = 1

然后關(guān)閉這個(gè)明細(xì)窗體:

self.destory()

另一邊,在主窗體中繼續(xù)完善add_student方法,在加載添加頁(yè)面的方法中傳入所有學(xué)生列表,和當(dāng)前學(xué)生信息。然后獲取明細(xì)窗體返回的值,刷新學(xué)生信息列表的Treeview,這樣添加學(xué)生信息,并且顯示在主窗體表格的功能就實(shí)現(xiàn)了。

def add_student(self):
    """
    添加學(xué)生信息
    """
    self.flag = 3
    # 加載添加的頁(yè)面
    detail = StudentDetail(self.flag, self.student_all, self.student_current)
    self.wait_window(detail)
    # 接受返回的值
    get_return_number = detail.userinfo
    # 如果為1 就刷新
    if get_return_number == 1:
        self.load_student_treeview()
3. 效果演示
1.gif

四、修改學(xué)生信息

1. 需求分析

上面我們講了添加學(xué)生信息,現(xiàn)在我們繼續(xù)將修改學(xué)生信息。我們需要完成的功能是在主界面表格中選擇某一行,點(diǎn)擊修改按鈕,打開修改明細(xì)窗口界面。

2. 實(shí)現(xiàn)過(guò)程

首先我們?cè)谥鹘缑嫘薷膶W(xué)生信息的方法中,在update_student方法中,修改flag,獲取當(dāng)前行的信息,最后再實(shí)例化明細(xì)窗體界面。這些操作與添加學(xué)生信息的過(guò)程基本一致,這里不做過(guò)多重復(fù)講解。

def update_student(self):
    """
    修改學(xué)生信息
    """
    # 修改flag
    self.flag = 2
    # 獲取當(dāng)前行的信息
    item = self.Tree_student.selection()[0]
    current_student = self.Tree_student.item(item,"values")
    for item in self.student_all:
        if current_student[0] == item[0]:
            self.student_current = item
    # 實(shí)例化界面
    detail = StudentDetail(self.flag, self.student_all, self.student_current)

接著,我們?cè)诿骷?xì)窗體中隊(duì)load_gui_by_flag方法再做完善,補(bǔ)充當(dāng)flag==2的情況。和查看明細(xì)窗口一樣,我們需要將主窗體表格中選中的學(xué)生信息填充到明細(xì)窗體中來(lái)。由于學(xué)號(hào)是不允許修改的,所以將學(xué)號(hào)輸入框禁用。

self.Entry_sno["state"] = DISABLED

效果演示:

圖片.png

然后在studentservices完善一下update方法,
我們通過(guò)循環(huán)遍歷list_all,判斷如果list_all中的學(xué)號(hào)與current_student學(xué)號(hào)相同,那么把明細(xì)窗體組建中的變量值賦值給list_all中匹配的那個(gè)學(xué)生信息。

# 主要通關(guān)過(guò)循環(huán)遍歷list,修改信息
for index in range(len(self.list_all)):
    if self.list_all[index][0] == self.student_current.sno:
        self.list_all[index][1] = self.student_current.name
        self.list_all[index][2] = self.student_current.gender
        self.list_all[index][3] = self.student_current.birthday
        self.list_all[index][4] = self.student_current.mobile
        self.list_all[index][5] = self.student_current.email
        self.list_all[index][6] = self.student_current.profession
        self.list_all[index][7] = self.student_current.entry_time

數(shù)據(jù)修改完成后,我們?cè)?code>commit方法中完善修改功能,與添加學(xué)生信息的操作一樣,我們需要封裝當(dāng)前學(xué)生類對(duì)象、校驗(yàn)輸入的學(xué)生信息是否符合要求、調(diào)用update方法修改列表、提示用戶修改成功、反饋信號(hào)給主窗體、最后關(guān)閉這個(gè)窗體。
然后我們?cè)谥鞔绑w界面中接收反饋,并刷新表格。
我們來(lái)看一下修改的動(dòng)作有沒有在主窗體表格中表現(xiàn)出來(lái)。
這樣,我們修改的動(dòng)作就已經(jīng)完成了,其實(shí)套路和添加學(xué)生信息一樣,現(xiàn)在我們演示一下將小新的專業(yè)改為“物聯(lián)網(wǎng)”,一下為演示效果:

1.gif

五、刪除學(xué)生信息

1.需求分析

我們希望這主窗體界面的表格中選中學(xué)生,然后點(diǎn)擊刪除按鈕,學(xué)生信息就被刪除掉。注意,以上包括添加、修改、已經(jīng)這里的刪除,其操作對(duì)象都是list,我們還并沒有保存到本地文件。寫入到本地文件等會(huì)我們會(huì)統(tǒng)一來(lái)做。
刪除操作,相對(duì)簡(jiǎn)單,因?yàn)樗恍枰谥鹘缑孢M(jìn)行,沒有跨越GUI,所有比較方便操作。

2.實(shí)現(xiàn)過(guò)程

我們首先把student_services模塊中的delete方法給寫好,我們同樣還是通過(guò)遍歷list_all,然后匹配選中項(xiàng),根據(jù)索引刪除該項(xiàng)。

def delete(self):
    # 主要通過(guò)循環(huán)遍歷list,刪除某條信息
    for index in range(len(self.list_all)):
        if self.list_all[index][0] == self.student_current.sno:
            # pop是根據(jù)索引號(hào)來(lái)刪除的
            self.list_all.pop(index)

緊接著,我們完善主窗體中的delete_studet方法,先獲取選中行的數(shù)據(jù),然后遍歷list_all,找到與被選中學(xué)生學(xué)號(hào)相同的項(xiàng)item,然后把該條學(xué)生項(xiàng)封裝成一個(gè)待刪除的對(duì)象student_object,實(shí)例化student_services后,彈出窗口詢問是否刪除,如果是則執(zhí)行刪除動(dòng)作,否則不刪除。

def delete_student(self):
    """
    刪除學(xué)生信息
    """
    # 獲取雙擊行的數(shù)據(jù)
    item = self.Tree_student.selection()[0]
    current_student = self.Tree_student.item(item, "values")
    student_object = ""
    for item in self.student_all:
        if current_student[0] == item[0]:
            # 封裝到student
            student_object = Student(item[1], item[2], item[3], item[4],
                                     item[5], item[0], item[6], item[7])
    # 實(shí)例化StudentServices
    current_student_services = StudentServices(self.student_all, student_object)
    # 詢問是否刪除
    choose = askyesno("刪除確認(rèn)","確認(rèn)要?jiǎng)h除學(xué)生信息【學(xué)號(hào):"+student_object.sno +
                      ",姓名:"+student_object.name+"】的信息嗎?")
    if choose:
        # 執(zhí)行刪除動(dòng)作
        current_student_services.delete()
        # 提醒刪除成功
        showinfo("系統(tǒng)消息", "學(xué)生消息刪除成功")
        # 更新表格
        self.load_student_treeview()
    else:
        return
3. 效果演示
1.gif

六、保存數(shù)據(jù)到文件

1. 需求分析

我們以上所做的所有增刪改都是對(duì)list進(jìn)行操作,當(dāng)程序重新打開后又恢復(fù)原樣了,我們最后需要做的是把操作結(jié)果寫入到文本文件中。

2. 實(shí)現(xiàn)過(guò)程

file類中,我們定義方法write_to_file,先把文本內(nèi)容清空,然后遍歷list_student_all中的每一個(gè)項(xiàng),用,填充在每一個(gè)項(xiàng)中,然后去除其中可能存在的換行符,但是在每一行的結(jié)束加上換行符。

def write_to_file(self):
    # ============ 把學(xué)生信息寫入文件 ========
    try:
        # 把原先的文件清空
        with open(self.student_path, mode="w", encoding="UTF-8") as fd_student:
            fd_student.write("")

        with open(self.student_path, mode="a", encoding="UTF-8") as fd_student:
            for item in self.list_student_all:
                temp = ",".join(item)
                temp = temp.replace("\n", "") + "\n" # 取出行中可能存在的換行符
                fd_student.write(temp)
    except Exception as e:
        raise e

寫入操作完成后,我們應(yīng)當(dāng)設(shè)置關(guān)閉窗口按鈕時(shí)觸發(fā)寫入文件操作。
我們需要把窗體關(guān)閉按鈕的行為轉(zhuǎn)化為方法,在主窗體的構(gòu)造函數(shù)中添加一個(gè)把窗體關(guān)閉按鈕的行為轉(zhuǎn)化為方法的語(yǔ)句。

self.protocol("WM_DELETE_WINDOW", self.close_window)

然后在下面定義close_window的方法,點(diǎn)擊窗口關(guān)閉按鈕時(shí)跳出彈窗,詢問是否保存修改,如果是則調(diào)用write_to_file方法寫入文件,寫入成功后系統(tǒng)彈窗提醒用戶已經(jīng)寫入成功,寫入成功后關(guān)閉窗體即可。

def close_window(self):
    # 詢問是否保存修改
    choose= askyesno("關(guān)閉前的提醒", "關(guān)閉窗體前是否要將修改寫入到文件?")
    if choose:
        try:
            self.file_info.write_to_file()
            showinfo("系統(tǒng)提示", "所有的修改已經(jīng)保存并寫入到文件")
            # 關(guān)閉窗口
            self.destroy()
        except Exception as e:
            showinfo("系統(tǒng)消息", e)
    else:
        self.destroy()

注意:即使點(diǎn)擊否,也要調(diào)用destory方法關(guān)閉窗口,否則窗體會(huì)陷入無(wú)法關(guān)閉的死循環(huán)。

3. 效果演示
1.gif

最后

以上,就是利用面向?qū)ο笏枷雽?shí)現(xiàn)學(xué)生教師信息管理的全部?jī)?nèi)容了,如果大家能手動(dòng)完成這個(gè)項(xiàng)目,必將對(duì)面向?qū)ο笏枷胗兄由羁痰睦斫狻?br> 配套的源碼及素材可以私信我獲取。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容