PyQt4百行代碼自制密碼管理器(三):數據庫引入

我們在這裏使用的是一個輕量級數據庫sqlite。Python2.5.x以上的版本默認自帶了sqlite3,大家可以試一下如果能成功import sqlite3就ok了。
首先我們需要一些預備知識。操作數據庫中的數據需要學習一種叫做SQL的語言,推薦w3school的教程:
http://www.w3school.com.cn/sql/
不需要系統學習,簡單瞭解一下就好。然後還需要學習一下sqlite在python中的基本操作方法,教程在這裏:
http://www.runoob.com/sqlite/sqlite-python.html
有了數據庫的知識,我們先來完成initDB()函數,完成每次程序啓動後都需要做的一些初始化操作。注意,現在我們的current_row就不能初始化爲0了,所以__init__(self)函數中self.current_row = 0這一句就沒什麼用了,可以刪去。還有,這裏我們使用了os.path.exists()函數,所以需要額外導入os包:import os。

initDB()

def initDB(self):
    if os.path.exists('info.db'):
        self.conn = sqlite3.connect('info.db')
        self.conn.isolation_level = None
    else:
        self.conn = sqlite3.connect('info.db')
        self.conn.isolation_level = None
        self.conn.execute('''CREATE TABLE INFO
                    (ID int PRIMARY KEY NOT NULL,
                    WEBSITE char(255),
                    USERNAME char(255),
                    PASSWORD char(255),
                    URL char(255))''')
    cur = self.conn.cursor()
    cur.execute('SELECT * FROM INFO')
    self.displayData = cur.fetchall()
    cur.close()
    self.current_row = len(self.displayData)

前面比較好理解,如果存在這個數據庫,就和它建立聯繫;如果不存在的話,就新建一個。

self.conn.isolation_level = None

這裏我們修改隔離等級是爲了圖方便,每次對數據庫操作之後不用commit就可以生效。
注意我們每個項目除了之前的四個數據之外,還加入了’ID’這一數據,ID爲數據所處的行數(從1開始計數),目的是通過給每條數據編號的方式使查找某一行的數據變得簡單,我們後面就會看到。

cur = self.conn.cursor()
cur.execute('SELECT * FROM INFO')
self.displayData = cur.fetchall()
cur.close()
self.current_row = len(self.displayData)

這裏我們建立了一個遊標(cursor),用來讀取已經在數據庫中的數據,並且獲得數據的條數。
接下來,我們需要修改之前已經寫好的三個分別具有new、edit、delete功能的函數,使用戶進行的操作可以同步修改數據庫中的數據。
新版newAction_def()

def newAction_def(self):
    data = self.showDialog()
    if data[0]:
        self.current_row += 1
        self.conn.execute("INSERT INTO INFO VALUES(%d, '%s', '%s', '%s', '%s')"
                          % (self.current_row, data[1], data[2], data[3], data[4]))
        self.grid.insertRow(self.current_row - 1)
        for i in range(4):
            new_item = QtGui.QTableWidgetItem(data[i + 1])
            self.grid.setItem(self.current_row - 1, i, new_item)

這裏我們用SQL中的insert語句將新的數據插入數據庫內。同樣,注意區分清楚行數和行號。
另外注意,%s兩邊的單引號必須帶,想一想爲什麼。

新版editAction_def()

def editAction_def(self):
    selected_row = self.grid.selectedItems()
    if selected_row:
        edit_row = self.grid.row(selected_row[0])
        old_data = []
        for i in range(4):
            old_data.append(self.grid.item(edit_row, i).text())
        new_data = self.showDialog(*old_data)
        if new_data[0]:
            self.conn.execute('''UPDATE INFO SET
                             WEBSITE = '%s', USERNAME = '%s',
                             PASSWORD = '%s', URL = '%s'
                             WHERE ID = '%d' '''
                          % (new_data[1], new_data[2], new_data[3], new_data[4], edit_row + 1))
            for i in range(4):
                new_item = QtGui.QTableWidgetItem(new_data[i + 1])
                self.grid.setItem(edit_row, i, new_item)
    else:
        self.showHint()

修改操作同樣也比較簡單,我們使用ID查找到要修改的數據,在數據庫、窗口中分別修改它。

新版delAction_def()

def delAction_def(self):
    selected_row = self.grid.selectedItems()
    if selected_row:
        del_row = self.grid.row(selected_row[0])
        self.grid.removeRow(del_row)
        print del_row
        self.conn.execute("DELETE FROM INFO WHERE ID = %d" % (del_row + 1))
        for index in range(del_row + 2, self.current_row + 1):
            self.conn.execute("UPDATE INFO SET ID = %d WHERE ID = %d" % ((index - 1), index))
        self.current_row -= 1
    else:
        self.showHint()

而del函數就要注意了,刪除某項之後,其後項目ID並不會自動改變,我們需要手動把後面的項目序號-1……就是下面這兩句:

for index in range(del_row + 2, self.current_row + 1):
    self.conn.execute("UPDATE INFO SET ID = %d WHERE ID = %d" % ((index - 1), index))

順求更好方法解決這個問題。
最後,我們在程序結束後關閉數據庫,於是我們將main函數改成這樣:

if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)
    pwk = PWKeeper()
    pwk.show()
    app.exec_()
    pwk.conn.close()
    sys.exit(0)

大功告成

這樣我們就大功告成啦!試着運行一下自己的密碼管理器,嘗試一下各種功能是否正常。關閉程序後,我們可以看見程序所在目錄下出現了一個.db的數據庫文件。
至此,我們已經完成了實現密碼管理器功能的所有代碼,有沒有很大的成就感呢!
程序設計中,代碼並不是最重要的,我們更需要掌握一些思想方法和學習方法,所以請務必閱讀一下看似沒有什麼用的下一節。
【持續更新中】

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章