SQLite
 sql >> база данни >  >> RDS >> SQLite

Създайте книга за контакти с Python, PyQt и SQLite

Изграждането на проекти е може би един от най-достъпните и ефективни начини за учене на програмиране. Реалните проекти изискват от вас да прилагате различни и разнообразни умения за кодиране. Те също така ви насърчават да изследвате теми, които се появяват, докато решавате проблеми в процеса на разработка. В този урок ще създадете приложение за книга за контакти с Python, PyQt и SQLite.

В този урок ще научите как да:

  • Създайте графичен потребителски интерфейс (GUI) за вашето приложение за книга с контакти, използващо Python и PyQt
  • Свържете приложението с SQLite база данни като използвате поддръжката на SQL на PyQt
  • Управлявайте данните за контакт с помощта на архитектурата на изглед на модел на PyQt

В края на този проект ще имате функционално приложение за контактна книга, което ще ви позволи да съхранявате и управлявате информацията си за контакт.

За да получите пълния изходен код за приложението, както и кода за всяка стъпка, през която ще преминете в този урок, щракнете върху връзката по-долу:

Вземете изходния код: Щракнете тук, за да получите изходния код, който ще използвате, за да създадете книга за контакти с Python, PyQt и SQLite в този урок.


Демо:Книга за контакти с Python

Книгите за контакти са полезен и широко използван вид приложение. те са навсякъде. Вероятно имате книга с контакти на телефона и на компютъра си. С указател за контакти можете да съхранявате и управлявате информация за контакт за членове на вашето семейство, приятели, колеги и т.н.

В този урок ще кодирате GUI приложение на книга за контакти с Python, SQLite и PyQt. Ето демонстрация на това как ще изглежда и работи вашата книга с контакти, след като изпълните стъпките в този урок:

Вашата книга за контакти ще предостави минимално необходимия набор от функции за този вид приложение. Ще можете да показвате, създавате, актуализирате и премахвате информацията в списъка си с контакти.



Преглед на проекта

За да изградите приложението си от книгата за контакти, трябва да организирате кода в модули и пакети и да придадете на проекта си съгласувана структура. В този урок ще използвате следните директории и файлова структура:

rpcontacts_project/
│
├── rpcontacts/
│   ├── __init__.py
│   ├── views.py
│   ├── database.py
│   ├── main.py
│   └── model.py
│
├── requirements.txt
├── README.md
└── rpcontacts.py

Ето кратко резюме на съдържанието на директорията на вашия проект:

  • rpcontacts_project/ е основната директория на проекта. Той ще съдържа следните файлове:
    • requirements.txt предоставя списък с изискванията на проекта.
    • README.md предоставя обща информация за проекта.
    • rpcontacts.py предоставя скрипта за входна точка за стартиране на приложението.
  • rpcontacts/ е поддиректория, която предоставя основния пакет на приложението. Той предоставя следните модули:
    • __init__.py
    • views.py
    • database.py
    • main.py
    • model.py

Ще разгледате всеки от тези файлове стъпка по стъпка в този урок. Името на всеки файл дава представа за ролята му в приложението. Например views.py ще съдържа кода за генериране на GUI на прозорци и диалози, database.py ще съдържа код за работа с базата данни и main.py ще хоства самото приложение. И накрая, model.py ще приложи модела за управление на данните в базата данни на приложението.

Като цяло приложението ще има основен прозорец за показване, добавяне, премахване и актуализиране на контакти. Освен това ще има диалогов прозорец за добавяне на нови контакти към базата данни.



Предварителни условия

За да извлечете максимума от този проект, някои предишни познания за GUI програмирането с Python и PyQt биха помогнали. В тази връзка ще трябва да знаете основите на това как да:

  • Създавайте GUI приложения с PyQt и Python
  • Създайте и изложете GUI с PyQt
  • Управлявайте SQL бази данни с Python и PyQt
  • Работа с бази данни на SQLite

За да освежите тези теми, можете да разгледате следните ресурси:

  • Python и PyQt:Създаване на настолен калкулатор с графичен интерфейс
  • Python и PyQt:Създаване на менюта, ленти с инструменти и ленти на състоянието
  • Оформления на PyQt:Създавайте професионално изглеждащи GUI приложения
  • Обработване на SQL бази данни с PyQt:Основите
  • Въведение в библиотеките на Python SQL
  • Управление на данни с Python, SQLite и SQLAlchemy

Не се притеснявайте, ако не сте експерт в тези области, преди да започнете този урок. Ще се научите чрез процеса на замърсяване на ръцете по реален проект. Ако се затрудните, отделете време и прегледайте ресурсите, свързани по-горе. След това се върнете към кода.

Приложението за контактна книга, което ще създадете в този урок, има една външна зависимост:PyQt.

Забележка: В този урок ще използвате PyQt версия 5.15.2, за да изградите приложението си от книгата с контакти. Необходима е версия 5.15.2, за да работи проектът на macOS Big Sur.

PyQt версия 6.0 беше пусната на 4 януари 2021 г. Това е първата версия на библиотеката, която се свързва с Qt версия 6. Проектът в този урок обаче не е тестван с PyQt 6.0.

Ако чувствате нужда да стартирате проекта с тази нова версия на PyQt, опитайте. Като намек, трябва да pip install PyQt6 и след това актуализирайте импортирането, за да използвате PyQt6 вместо PyQt5 .

За да следвате най-добрите практики в процеса на разработка, можете да започнете със създаване на виртуална среда и след това да инсталирате PyQt с помощта на pip . След като инсталирате PyQt, сте готови да започнете да кодирате!



Стъпка 1:Създаване на приложението Skeleton на книгата за контакти с PyQt

В тази първа стъпка ще създадете минимално, но функционално PyQt GUI приложение, за да осигурите основата, върху която ще започнете да изграждате книгата с контакти. Вие също така ще създадете минимално необходимата структура на проекта, включително основния пакет на проекта и скрипт за входна точка за стартиране на приложението.

Всички кодове и файлове, които ще добавите към проекта на книгата с контакти в този раздел, се събират под source_code_step_1/ директория. Можете да ги изтеглите, като щракнете върху връзката по-долу:

Вземете изходния код: Щракнете тук, за да получите изходния код, който ще използвате, за да създадете книга за контакти с Python, PyQt и SQLite в този урок.

До края на този раздел ще можете да стартирате скелетното GUI приложение за вашата книга с контакти за първи път.


Структуриране на проекта за контактна книга

За да започнете да кодирате приложението, продължете и създайте нова директория, наречена rpcontacts_project/ . Това ще бъде основната директория на проекта. Сега създайте нова поддиректория, наречена rpcontacts/ вътре в rpcontacts_project/ . Тази поддиректория ще съдържа основния пакет на приложението. Накрая стартирайте вашия редактор на код или IDE в главната директория.

За да превърне директория в пакет, Python се нуждае от __init__.py модул за инициализиране на пакета. Създайте този файл в rpcontacts/ и добавете следния код към него:

# -*- coding: utf-8 -*-

"""This module provides the rpcontacts package."""

__version__ = "0.1.0"

Този файл казва на Python, че rpcontacts е пакет. Кодът във файла се изпълнява, когато импортирате пакета или някои от неговите модули.

Не е необходимо да поставяте никакъв код в __init__.py файл за инициализиране на пакета. Празен __init__.py файл ще свърши работа. В този случай обаче дефинирате константа на ниво модул, наречена __version__ за да запазите номера на версията на вашето приложение.



Създаване на главния прозорец на приложението

Сега е време да създадете главния прозорец на вашата книга с контакти. За да направите това, създайте модул, наречен views.py във вашите rpcontacts пакет. След това добавете следния код към модула и го запазете:

# -*- coding: utf-8 -*-

"""This module provides views to manage the contacts table."""

from PyQt5.QtWidgets import (
    QHBoxLayout,
    QMainWindow,
    QWidget,
)

class Window(QMainWindow):
    """Main Window."""
    def __init__(self, parent=None):
        """Initializer."""
        super().__init__(parent)
        self.setWindowTitle("RP Contacts")
        self.resize(550, 250)
        self.centralWidget = QWidget()
        self.setCentralWidget(self.centralWidget)
        self.layout = QHBoxLayout()
        self.centralWidget.setLayout(self.layout)

Първо импортирате необходимите класове от PyQt5.QtWidgets . След това създавате Window . Този клас наследява от QMainWindow и предоставя кода за генериране на главния прозорец на приложението. В метода на инициализатора задавате заглавието на прозореца на "RP Contacts" , преоразмерете прозореца до 550 с 250 пиксели, дефинирайте и задайте централната джаджа с помощта на QWidget и накрая дефинирайте оформление за централната джаджа, като използвате хоризонтално оформление на кутия.



Кодиране и стартиране на приложението

Тъй като вече имате основен прозорец за книгата с контакти, време е да напишете кода за създаване на функционално PyQt приложение с помощта на QApplication . За да направите това, създайте нов модул, наречен main.py във вашите rpcontacts пакет и добавете следния код към него:

# -*- coding: utf-8 -*-
# rpcontacts/main.py

"""This module provides RP Contacts application."""

import sys

from PyQt5.QtWidgets import QApplication

from .views import Window

def main():
    """RP Contacts main function."""
    # Create the application
    app = QApplication(sys.argv)
    # Create the main window
    win = Window()
    win.show()
    # Run the event loop
    sys.exit(app.exec())

В този модул импортирате sys за да получите достъп до exit() , което ви позволява да излезете чисто от приложението, когато потребителят затвори главния прозорец. След това импортирате QApplication от PyQt5.QtWidgets и Window от views . Последната стъпка е да дефинирате main() като основна функция на приложението ви.

Вътре в main() , вие инстанцирате QApplication и Window . След това извиквате .show() в Window , и накрая стартирате основния цикъл на приложението , или примка за събитие , като използвате .exec() .

Сега преминете нагоре към основната директория на проекта rpcontacts_project/ и създайте файл, наречен rpcontacts.py . Този файл предоставя скрипта за входна точка за стартиране на приложението. Добавете следния код към файла и го запазете:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# rpcontacts_project/rpcontacts.py

"""This module provides RP Contacts entry point script."""

from rpcontacts.main import main

if __name__ == "__main__":
    main()

Този файл импортира main() от вашия main.py модул. След това прилагате традиционния условен израз, който извиква main() ако потребителят стартира този модул като скрипт на Python. Сега стартирайте приложението, като изпълните командата python rpcontacts.py във вашата среда на Python. Ще получите следния прозорец на екрана си:

Това е! Създадохте минимално, но функционално PyQt GUI приложение, което можете да използвате като отправна точка за изграждане на вашата книга с контакти. В този момент вашият проект трябва да има следната структура:

./rpcontacts_project/
│
├── rpcontacts/
│   ├── __init__.py
│   ├── views.py
│   └── main.py
│
└── rpcontacts.py

В този раздел сте създали минималната необходима структура за вашия проект с книга за контакти, използвайки модули и пакети на Python. Изградихте главния прозорец на приложението и сте събрали стандартния код, за да създадете PyQt GUI приложение. Също така сте стартирали приложението за първи път. След това ще започнете да добавяте функции към вашия GUI.




Стъпка 2:Създаване на GUI на книгата за контакти с Python

След като сте изградили скелета на приложението си за книга с контакти, можете да започнете да кодирате GUI на главния прозорец. В края на този раздел ще завършите необходимите стъпки за създаване на GUI на вашата книга с контакти с помощта на Python и PyQt. GUI ще изглежда така:

В центъра на прозореца имате изглед на таблица, за да покажете списъка си с контакти. От дясната страна на формуляра имате три бутона:

  1. Добавяне за да добавите нов контакт към списъка
  2. Изтриване за да премахнете избран контакт от списъка
  3. Изчистване на всички за да премахнете всички контакти от списъка

Всички кодове и файлове, които ще добавите или промените в този раздел, се събират под source_code_step_2/ директория. Можете да ги изтеглите, като щракнете върху връзката по-долу:

Вземете изходния код: Щракнете тук, за да получите изходния код, който ще използвате, за да създадете книга за контакти с Python, PyQt и SQLite в този урок.

Върнете се към views.py модул и актуализирайте кода на Window за генериране на горния GUI:

 1# -*- coding: utf-8 -*-
 2# rpcontacts/views.py
 3
 4"""This module provides views to manage the contacts table."""
 5
 6from PyQt5.QtWidgets import (
 7    QAbstractItemView,
 8    QHBoxLayout,
 9    QMainWindow,
10    QPushButton,
11    QTableView,
12    QVBoxLayout,
13    QWidget,
14)
15
16class Window(QMainWindow):
17    """Main Window."""
18    def __init__(self, parent=None):
19        """Initializer."""
20        # Snip...
21
22        self.setupUI()
23
24    def setupUI(self):
25        """Setup the main window's GUI."""
26        # Create the table view widget
27        self.table = QTableView()
28        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
29        self.table.resizeColumnsToContents()
30        # Create buttons
31        self.addButton = QPushButton("Add...")
32        self.deleteButton = QPushButton("Delete")
33        self.clearAllButton = QPushButton("Clear All")
34        # Lay out the GUI
35        layout = QVBoxLayout()
36        layout.addWidget(self.addButton)
37        layout.addWidget(self.deleteButton)
38        layout.addStretch()
39        layout.addWidget(self.clearAllButton)
40        self.layout.addWidget(self.table)
41        self.layout.addLayout(layout)

Първо импортирате някои допълнителни PyQt класове, които да използвате в GUI. Ето някои от по-подходящите:

  • QPushButton за да създадете Добавяне , Изтриване и Изчистване на всички бутони
  • QTableView за да предоставите изглед, подобен на таблица, който показва списъка с контакти
  • QAbstractItemView за предоставяне на достъп до политиката за поведение при избор на изглед на таблица

В този код, първото допълнение към Window е извикване на .setupUI() в края на __init__() . Това извикване генерира GUI на главния прозорец, когато стартирате приложението.

Ето какъв е кодът в .setupUI() прави:

  • Ред 27 създава QTableView екземпляр за показване на списъка с контакти.
  • Ред 28 задава .selectionBehavior свойство на QAbstractItemView.SelectRows . Това гарантира, че когато потребител щракне върху която и да е клетка от изгледа на таблицата, ще бъде избран целият ред. Редовете в изгледа на таблицата съдържат цялата информация, свързана с един контакт в списъка с контакти.
  • Редове от 31 до 33 добавете трите бутона към GUI:Добавяне , Изтриване и Изчистване на всички . Тези бутони все още не извършват никакви действия.
  • Редове от 35 до 41 създайте и задайте съгласувано оформление за всички джаджи в графичния интерфейс.

С тези допълнения към Window , можете да стартирате приложението отново. Прозорецът на вашия екран ще изглежда като прозореца, който видяхте в началото на секцията.

Забележка: Номерата на редовете в горния код и в останалата част от примерните кодове в този урок са предназначени да улеснят обяснението. Те не съответстват на реда на редовете в крайния модул или скрипт.

В този раздел сте изпълнили всички необходими стъпки, за да създадете GUI на главния прозорец на вашата книга с контакти. Вече сте готови да започнете да работите върху това как приложението ви ще управлява и съхранява вашите данни за контакт.



Стъпка 3:Настройване на базата данни на книгата за контакти

В този момент сте създали приложение PyQt и графичния интерфейс на главния му прозорец, за да изградите своя проект за книга с контакти. В този раздел ще напишете код, за да дефинирате как приложението се свързва с базата данни с контакти. За да завършите тази стъпка, ще използвате SQLite за обработка на базата данни и SQL поддръжката на PyQt, за да свържете приложението към базата данни и да работите с вашите данни за контакт.

Изходният код и файловете, които ще добавите или промените в този раздел, се съхраняват под source_code_step_3/ директория. Можете да ги изтеглите, като щракнете върху връзката по-долу:

Вземете изходния код: Щракнете тук, за да получите изходния код, който ще използвате, за да създадете книга за контакти с Python, PyQt и SQLite в този урок.

Първо се върнете към main.py в rpcontacts/ директория и актуализирайте кода, за да създадете връзката с базата данни:

# -*- coding: utf-8 -*-
# rpcontacts/main.py

"""This module provides RP Contacts application."""

import sys

from PyQt5.QtWidgets import QApplication

from .database import createConnection
from .views import Window

def main():
    """RP Contacts main function."""
    # Create the application
    app = QApplication(sys.argv)
    # Connect to the database before creating any window
    if not createConnection("contacts.sqlite"):
        sys.exit(1)
    # Create the main window if the connection succeeded
    win = Window()
    win.show()
    # Run the event loop
    sys.exit(app.exec_())

В този случай първо импортирате createConnection() от database.py . Тази функция ще съдържа код за създаване и отваряне на връзка с базата данни с контакти. Ще създадете database.py и напишете createConnection() в следващия раздел.

Вътре в main() , първият маркиран ред е опит за създаване на връзка с базата данни с помощта на createConnection() . Ако по някаква причина приложението не може да създаде връзка, тогава извикването на sys.exit(1) ще затвори приложението, без да създава графичен елемент и ще покаже, че е възникнала грешка.

Трябва да се справите с връзката по този начин, защото приложението зависи от базата данни, за да работи правилно. Ако нямате функционална връзка, приложението ви изобщо няма да работи.

Тази практика ви позволява да обработвате грешки и да затваряте чисто приложението, ако възникне проблем. Също така ще можете да представите на потребителя подходяща информация за грешката, в която приложението се е натъкнало при опит да се свърже с базата данни.

С тези допълнения на място е време да се потопите в кода на createConnection() .


Свързване с базата данни с PyQt и SQLite

Свързването на вашето приложение от книгата за контакти към свързаната с него база данни е основна стъпка в разработването на приложението. За да направите това, ще кодирате функция, наречена createConnection() , което ще създаде и отвори връзка с базата данни. Ако връзката е успешна, тогава функцията ще върне True . В противен случай ще предостави информация за причината за неуспеха на връзката.

Върнете се към rpcontacts/ директория и създайте нов модул, наречен database.py в него. След това добавете следния код към този модул:

 1# -*- coding: utf-8 -*-
 2# rpcontacts/database.py
 3
 4"""This module provides a database connection."""
 5
 6from PyQt5.QtWidgets import QMessageBox
 7from PyQt5.QtSql import QSqlDatabase
 8
 9def createConnection(databaseName):
10    """Create and open a database connection."""
11    connection = QSqlDatabase.addDatabase("QSQLITE")
12    connection.setDatabaseName(databaseName)
13
14    if not connection.open():
15        QMessageBox.warning(
16            None,
17            "RP Contact",
18            f"Database Error: {connection.lastError().text()}",
19        )
20        return False
21
22    return True

Тук първо импортирате някои необходими PyQt класове. След това дефинирате createConnection() . Тази функция приема един аргумент:databaseName съдържа името или пътя към физическия файл на база данни на SQLite във вашата файлова система.

Ето какъв е кодът вътре в createConnection() прави:

  • Ред 11 създава връзката с базата данни с помощта на QSQLITE шофьор.
  • Ред 12 задава името на файла или пътя към базата данни.
  • Ред 14 се опитва да отвори връзката. Ако възникне проблем по време на извикването на .open() , след това if кодовият блок показва съобщение за грешка и след това връща False за да покаже, че опитът за свързване е неуспешен.
  • Ред 22 връща True ако опитът за свързване е успешен.

Вече сте кодирали createConnection() . Сега можете да напишете кода за създаване на contacts таблици в базата данни.



Създаване на contacts Таблица

С функцията, която създава и отваря връзката с базата данни, можете да продължите да кодирате помощна функция за създаване на contacts маса. Ще използвате тази таблица, за да съхранявате информацията за вашите контакти.

Ето кода, който имплементира _createContactsTable() :

# -*- coding: utf-8 -*-
# rpcontacts/database.py

# Snip...
from PyQt5.QtSql import QSqlDatabase, QSqlQuery

def _createContactsTable():
    """Create the contacts table in the database."""
    createTableQuery = QSqlQuery()
    return createTableQuery.exec(
        """
        CREATE TABLE IF NOT EXISTS contacts (
            id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL,
            name VARCHAR(40) NOT NULL,
            job VARCHAR(50),
            email VARCHAR(40) NOT NULL
        )
        """
    )

def createConnection(databaseName):
    # Snip...
    _createContactsTable()
    return True

Тук първо добавяте нов импорт. Вие импортирате QSqlQuery за изпълнение и манипулиране на SQL изрази.

Вътре в _createContactsTable() , създавате QSqlQuery екземпляр. След това извиквате .exec() върху обекта на заявката с базиран на низ SQL CREATE TABLE твърдение като аргумент. Този израз създава нова таблица, наречена contacts във вашата база данни. Таблицата има следните колони:

Колона Съдържание
id Цяло число с първичен ключ на таблицата
name Низ с името на контакт
job Низ с длъжността на контакт
email Низ с имейл на контакт

contacts таблица във вашата база данни ще съхранява подходяща информация за вашите контакти.

Последната стъпка за завършване на кодирането на database.py е да добавите извикване към _createContactsTable() от вътрешността на createConnection() , точно преди последното return изявление. Това гарантира, че приложението създава contacts таблица, преди да извършите каквито и да е операции с базата данни.

След като създадете contacts таблица, можете да стартирате някои тестове в базата данни и също така да добавите някои примерни данни за по-нататъшно тестване.



Тестване на базата данни на книгата за контакти

Досега сте приключили с писането на необходимия код за обработка на връзката с базата данни на книгата с контакти. В този раздел ще извършите някои тестове, за да се уверите, че този код и самата база данни работят правилно. Също така ще добавите някои примерни данни към базата данни, за да извършите допълнително тестване по-късно в този урок.

Сега отворете терминал или команден ред и преминете към основната директория на проекта, rpcontacts_project/ . Веднъж там, стартирайте интерактивна сесия на Python и въведете следния код:

>>>
>>> from rpcontacts.database import createConnection

>>> # Create a connection
>>> createConnection("contacts.sqlite")
True

>>> # Confirm that contacts table exists
>>> from PyQt5.QtSql import QSqlDatabase
>>> db = QSqlDatabase.database()
>>> db.tables()
['contacts', 'sqlite_sequence']

Тук първо импортирате createConnection() от database.py модул. След това извиквате тази функция, за да създадете и отворите връзка с базата данни с контакти. Името на файла на базата данни е contacts.sqlite . Тъй като този файл не съществува в основната директория на проекта, SQLite го създава за вас. Можете да проверите това, като погледнете текущата си директория.

След това потвърждавате, че базата данни съдържа таблица, наречена contacts . За да направите това, извиквате .database() на QSqlDatabase . Този метод на клас връща указател към текущата връзка с базата данни. С тази препратка към връзката можете да извикате .tables() за да получите списъка с таблици в базата данни. Имайте предвид, че първата таблица в списъка е contacts , така че сега сте сигурни, че всичко работи добре.

Сега можете да подготвите SQL заявка за вмъкване на примерни данни в contacts таблица:

>>>
>>> # Prepare a query to insert sample data
>>> from PyQt5.QtSql import QSqlQuery

>>> insertDataQuery = QSqlQuery()
>>> insertDataQuery.prepare(
...     """
...     INSERT INTO contacts (
...         name,
...         job,
...         email
...     )
...     VALUES (?, ?, ?)
...     """
... )
True

Горната заявка ви позволява да вмъкнете конкретни стойности в name , job и email атрибути и да запишете тези стойности в базата данни. По-долу е даден пример как да направите това:

>>>
>>> # Sample data
>>> data = [
...     ("Linda", "Technical Lead", "[email protected]"),
...     ("Joe", "Senior Web Developer", "[email protected]"),
...     ("Lara", "Project Manager", "[email protected]"),
...     ("David", "Data Analyst", "[email protected]"),
...     ("Jane", "Senior Python Developer", "[email protected]"),
... ]

>>> # Insert sample data
>>> for name, job, email in data:
...     insertDataQuery.addBindValue(name)
...     insertDataQuery.addBindValue(job)
...     insertDataQuery.addBindValue(email)
...     insertDataQuery.exec()
...
True
True
True
True
True

В тази част от кода първо дефинирате data да съхранява информацията за контакт на списък с хора. След това използвате for цикъл за вмъкване на данните чрез извикване на .addBindValue() . След това извиквате .exec() върху обекта на заявката, за да изпълните ефективно SQL заявката в базата данни.

Тъй като всички извиквания към .exec() върнете True , можете да заключите, че данните са били успешно вмъкнати в базата данни. Ако искате да потвърдите това, изпълнете следния код:

>>>
>>> query = QSqlQuery()
>>> query.exec("SELECT name, job, email FROM contacts")
True

>>> while query.next():
...     print(query.value(0), query.value(1), query.value(2))
...
Linda Technical Lead [email protected]
Joe Senior Web Developer [email protected]
Lara Project Manager [email protected]
David Data Analyst [email protected]
Jane Senior Python Developer [email protected]

Това е! Вашата база данни работи добре! Сега имате някои примерни данни, с които да тествате приложението, и можете да се съсредоточите върху това как да заредите и покажете информацията за контакт в главния прозорец на вашата книга с контакти.




Стъпка 4:Показване и актуализиране на съществуващи контакти

За да покажете данните си за контакт в главния прозорец на приложението, можете да използвате QTableView . Този клас е част от архитектурата Model-View на PyQt и осигурява стабилен и ефективен начин за показване на елементи от обект на модел на PyQt.

Файловете и кодът, който ще добавите или промените в този раздел, се съхраняват под source_code_step_4/ директория. За да ги изтеглите, щракнете върху връзката по-долу:

Вземете изходния код: Щракнете тук, за да получите изходния код, който ще използвате, за да създадете книга за контакти с Python, PyQt и SQLite в този урок.

След като завършите тази стъпка, вашата книга с контакти ще изглежда така:

Обектът за изглед на таблица в главния прозорец предоставя необходимата функционалност, за да ви позволи бързо да променяте и актуализирате информацията за контакт.

Например, за да актуализирате името на контакт, можете да щракнете двукратно върху клетката, съдържаща името, да актуализирате името и след това да натиснете Enter за автоматично запазване на промените в базата данни. Но преди да можете да направите това, трябва да създадете модел и да го свържете с изгледа на таблицата.


Създаване на модел за обработка на данните за контакт

PyQt предоставя богат набор от класове за работа със SQL бази данни. За приложението си в книгата с контакти ще използвате QSqlTableModel , който предоставя редактируем модел на данни за една таблица на база данни. Той е идеален за работата, тъй като вашата база данни има една таблица, contacts .

Върнете се към вашия редактор на код и създайте нов модул, наречен model.py вътре в rpcontacts/ директория. Добавете следния код към файла и го запазете:

 1# -*- coding: utf-8 -*-
 2# rpcontacts/model.py
 3
 4"""This module provides a model to manage the contacts table."""
 5
 6from PyQt5.QtCore import Qt
 7from PyQt5.QtSql import QSqlTableModel
 8
 9class ContactsModel:
10    def __init__(self):
11        self.model = self._createModel()
12
13    @staticmethod
14    def _createModel():
15        """Create and set up the model."""
16        tableModel = QSqlTableModel()
17        tableModel.setTable("contacts")
18        tableModel.setEditStrategy(QSqlTableModel.OnFieldChange)
19        tableModel.select()
20        headers = ("ID", "Name", "Job", "Email")
21        for columnIndex, header in enumerate(headers):
22            tableModel.setHeaderData(columnIndex, Qt.Horizontal, header)
23        return tableModel

В този код първо правите някои необходими импортирания, след което създавате ContactsModel . В инициализатора на класа дефинирате атрибут на екземпляр, наречен .model за да задържите модела на данни.

Next, you add a static method to create and set up the model object. Here’s what the code in ._createModel() does:

  • Line 16 creates an instance of QSqlTableModel() called tableModel .
  • Line 17 associates the model object with the contacts table in your database.
  • Line 18 sets the .editStrategy property of the model to QSqlTableModel.OnFieldChange . With this, you ensure that the changes on the model get saved into the database immediately.
  • Line 19 loads the table into the model by calling .select() .
  • Lines 20 to 22 define and set user-friendly headers for the contacts table’s columns.
  • Line 23 returns the newly created model.

At this point, you have your data model ready to use. Now you need to connect the table view widget to the model so you can present your users with the contact information.



Connecting the Model to the View

To display contact data in your contact book’s main window, you need to connect the table view with the data model. To perform this connection, you need to call .setModel() on the table view object and pass the model as an argument:

# -*- coding: utf-8 -*-
# rpcontacts/views.py

# Snip...
from .model import ContactsModel

class Window(QMainWindow):
    """Main Window."""
    def __init__(self, parent=None):
        # Snip...
        self.contactsModel = ContactsModel()
        self.setupUI()

    def setupUI(self):
        """Setup the main window's GUI."""
        # Create the table view widget
        self.table = QTableView()
        self.table.setModel(self.contactsModel.model)
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        # Snip...

In this code, you first import ContactsModel from model.py . This class provides the model that manages the data in your contact database.

In the initializer of Window , you create an instance of ContactsModel . Then inside .setupUI() , you call .setModel() on .table to connect the model with the table view. If you run the application after this update, then you’ll get the window you saw at the beginning of step 4.



Displaying and Updating Contacts

PyQt’s Model-View architecture provides a robust and user-friendly way to create GUI applications that manage databases. Models communicate with and access the data in the database. Any change in a model updates the database immediately. Views are responsible for displaying the data to the user and also for providing editable widgets to allow the user to modify the data directly in the view.

If the user modifies the data through the view, then the view internally communicates with and updates the model, which saves the changes to the physical database:

In this example, you double-click Joe’s Job поле. This gives you access to an editable widget that allows you to modify the value in the cell. Then you update the job description from Senior Web Developer to Web Developer . When you hit Enter , the table view communicates the change to the model, and the model saves the change to the database immediately.

To confirm that the changes were successfully saved into the database, you can close the application and run it again. The table view should reflect your updates.




Step 5:Creating New Contacts

At this step, your contact book application provides functionality to load, display, and update the information about your contacts. Even though you’re able to modify and update the contact information, you can neither add nor remove contacts from the list.

All the files and the code you’ll add or modify in this section are collected in the source_code_step_5/ директория. To download them, click the link below:

Get the Source Code: Click here to get the source code you’ll use to build a contact book with Python, PyQt, and SQLite in this tutorial.

In this section, you’ll provide the required functionality to add new contacts to the database, using a pop-up dialog to enter the new information. The first step is to create the Add Contact dialog.


Creating the Add Contact Dialog

Dialogs are small windows that you can use to communicate with your users. In this section, you’ll code the contact book’s Add Contact dialog to allow your users add new contacts to their current list of contacts.

To code the Add Contact dialog, you’ll subclass QDialog . This class provides a blueprint to build dialogs for your GUI applications.

Now open the views.py module and update the import section like this:

# -*- coding: utf-8 -*-
# rpcontacts/views.py

# Snip...
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
    QAbstractItemView,
    QDialog,
    QDialogButtonBox,
    QFormLayout,
    QHBoxLayout,
    QLineEdit,
    QMainWindow,
    QMessageBox,
    QPushButton,
    QTableView,
    QVBoxLayout,
    QWidget,
)

The highlighted lines in the above code import the required classes to build the Add Contact dialog. With these classes in your namespace, add the following class at the end of views.py :

 1# -*- coding: utf-8 -*-
 2# rpcontacts/views.py
 3
 4# Snip...
 5class AddDialog(QDialog):
 6    """Add Contact dialog."""
 7    def __init__(self, parent=None):
 8        """Initializer."""
 9        super().__init__(parent=parent)
10        self.setWindowTitle("Add Contact")
11        self.layout = QVBoxLayout()
12        self.setLayout(self.layout)
13        self.data = None
14
15        self.setupUI()
16
17    def setupUI(self):
18        """Setup the Add Contact dialog's GUI."""
19        # Create line edits for data fields
20        self.nameField = QLineEdit()
21        self.nameField.setObjectName("Name")
22        self.jobField = QLineEdit()
23        self.jobField.setObjectName("Job")
24        self.emailField = QLineEdit()
25        self.emailField.setObjectName("Email")
26        # Lay out the data fields
27        layout = QFormLayout()
28        layout.addRow("Name:", self.nameField)
29        layout.addRow("Job:", self.jobField)
30        layout.addRow("Email:", self.emailField)
31        self.layout.addLayout(layout)
32        # Add standard buttons to the dialog and connect them
33        self.buttonsBox = QDialogButtonBox(self)
34        self.buttonsBox.setOrientation(Qt.Horizontal)
35        self.buttonsBox.setStandardButtons(
36            QDialogButtonBox.Ok | QDialogButtonBox.Cancel
37        )
38        self.buttonsBox.accepted.connect(self.accept)
39        self.buttonsBox.rejected.connect(self.reject)
40        self.layout.addWidget(self.buttonsBox)

There are a lot of things happening in this code. Here’s a summary:

  • Line 5 defines a new class that inherits from QDialog .
  • Lines 7 to 15 define the class initializer. In this case, the most relevant addition is .data , which is an instance attribute that you’ll use to hold the data your users provide.

In .setupUI() , you define the dialog’s GUI:

  • Lines 20 to 25 add three QLineEdit objects:name , job , and email . You’ll use these line edits to take the user’s input for the name, job description, and email of the contact to add. They represent the corresponding fields in the database.
  • Lines 27 to 30 create a QFormLayout instance that arranges the line edits in a form. This layout manager also provides user-friendly labels for each line edit or field.
  • Lines 33 to 37 add a QDialogButtonBox object that provides two standard buttons:OK and Cancel . The OK button accepts the user’s input and the Cancel button rejects it.
  • Lines 38 and 39 connect the dialog’s built-in .accepted() and .rejected() signals with the .accept() and reject() slots, respectively. In this case, you’ll rely on the dialog’s built-in .reject() slot, which closes the dialog without processing the input. Other than that, you just need to code the .accept() slot.

To code the dialog’s .accept() slot, you need to consider that any user input needs validation to make sure that it’s correct and safe. This is especially true when you’re working with SQL databases because of the risk of an SQL injection attack.

In this example, you’ll add a minimal validation rule just to make sure that the user provides data for each input field in the dialog. However, adding your own, more robust validation rules would be a good exercise.

Without further ado, get back to AddDialog and add the following code for its .accept() slot:

 1# -*- coding: utf-8 -*-
 2# rpcontacts/views.py
 3
 4# Snip...
 5class AddDialog(QDialog):
 6    def __init__(self, parent=None):
 7        # Snip...
 8
 9    def setupUI(self):
10        # Snip...
11
12    def accept(self):
13        """Accept the data provided through the dialog."""
14        self.data = []
15        for field in (self.nameField, self.jobField, self.emailField):
16            if not field.text():
17                QMessageBox.critical(
18                    self,
19                    "Error!",
20                    f"You must provide a contact's {field.objectName()}",
21                )
22                self.data = None  # Reset .data
23                return
24
25            self.data.append(field.text())
26
27        if not self.data:
28            return
29
30        super().accept()

The code within .accept() does the following:

  • Line 14 initializes .data to an empty list ([] ). This list will store the user’s input data.
  • Line 15 defines a for loop that iterates over the three line edits, or fields, in the dialog.
  • Lines 16 to 23 define a conditional statement that checks if the user has provided data for each field in the dialog. If not, then the dialog shows an error message that warns the user about the missing data.
  • Line 25 adds the user’s input for each field to .data .
  • Line 30 calls the superclass’s .accept() slot to provide the standard behavior that closes the dialog after the user clicks OK .

With this code, you’re ready to add a new slot to the contact book’s main window. This slot will launch the dialog, and if the user provides valid input, then the slot will use the model to save the newly added contact to the database.



Launching the Add Contact Dialog

Now that you’ve coded the Add Contact dialog, it’s time to add a new slot to Window so you can launch the dialog by clicking Add and process the user’s input once they click OK .

Go to the definition of Window and add the following code:

 1# -*- coding: utf-8 -*-
 2# rpcontacts/views.py
 3
 4# Snip...
 5class Window(QMainWindow):
 6    # Snip...
 7
 8    def setupUI(self):
 9        # Snip...
10        self.addButton = QPushButton("Add...")
11        self.addButton.clicked.connect(self.openAddDialog)
12        # Snip...
13
14    def openAddDialog(self):
15        """Open the Add Contact dialog."""
16        dialog = AddDialog(self)
17        if dialog.exec() == QDialog.Accepted:
18            self.contactsModel.addContact(dialog.data)
19            self.table.resizeColumnsToContents()

Here’s a summary of what’s happening in the above code:

  • Line 11 connects the .clicked() signal of the Add button to the newly created slot, .openAddDialog() . This way, a click on the button will automatically call the slot.
  • Line 14 defines the .openAddDialog() slot.
  • Line 16 creates an instance of AddDialog .
  • Lines 17 to 19 define a conditional statement to check if the dialog was accepted. If so, then line 14 calls .addContact() on the data model with the dialog’s .data attribute as an argument. The final statement in the if code block resizes the table view to fit the size of its updated content.

Now that you have a way to launch the Add Contact dialog and to process its data, you need to provide the code for .addContact() in your data model. That’s a topic for the next section.



Processing the Add Dialog’s Data in the Model

In this section, you’ll add a method called .addContact() to your data model, ContactsModel . Open model.py in your code editor, go to the definition of ContactsModel , and add the following code:

 1# -*- coding: utf-8 -*-
 2# rpcontacts/model.py
 3
 4# Snip...
 5class ContactsModel:
 6    # Snip...
 7
 8    def addContact(self, data):
 9        """Add a contact to the database."""
10        rows = self.model.rowCount()
11        self.model.insertRows(rows, 1)
12        for column, field in enumerate(data):
13            self.model.setData(self.model.index(rows, column + 1), field)
14        self.model.submitAll()
15        self.model.select()

Inside .addContact() , the code does the following:

  • Line 10 gets the current number of rows in the data model.
  • Line 11 inserts a new row at the end of the data model.
  • Lines 12 and 13 run a for loop that inserts every item in data into the corresponding cell in the data model. To do this, line 9 calls .setData() on the model, with the index of the cell and the current data field as arguments.
  • Line 14 submits the changes to the database by calling .submitAll() on the model.
  • Line 15 reloads the data from the database into the model.

If you run the application with these new additions, then you’ll get the following behavior:

Now when you click Add , the Add Contact dialog appears on your screen. You can use the dialog to provide the required information for a new contact and to add the contact to the database by clicking OK .




Step 6:Deleting Existing Contacts

The final feature you’ll add to the contact book application is the ability to remove contacts from the database using the GUI.

Again, you’ll find all the files and the code added or modified in this section under the source_code_step_6/ директория. You can download them by clicking the link below:

Get the Source Code: Click here to get the source code you’ll use to build a contact book with Python, PyQt, and SQLite in this tutorial.

In this section, you’ll first add the capability to delete a single contact at a time. Then you’ll add code to remove all the contacts from the database.


Deleting Selected Contacts

To remove a single contact from the contact database, you need to select the desired contact in the table view on the contact book’s main window. Once you’ve selected the contact, you can click Delete to perform the operation on the database.

Go to the model.py module and add the following code to implement .deleteContact() inside ContactsModel :

# -*- coding: utf-8 -*-
# rpcontacts/model.py

# Snip...
class ContactsModel:
    # Snip...

    def deleteContact(self, row):
        """Remove a contact from the database."""
        self.model.removeRow(row)
        self.model.submitAll()
        self.model.select()

This method has three lines of code. The first line removes the selected row . The second line submits the change to the database. Finally, the third line reloads the data into the model.

Next, get back to the views.py module and add the code behind the Delete button in Window :

# -*- coding: utf-8 -*-
# rpcontacts/views.py

# Snip...
class Window(QMainWindow):
    # Snip...

    def setupUI(self):
        """Setup the main window's GUI."""
        # Snip...
        self.deleteButton = QPushButton("Delete")
        self.deleteButton.clicked.connect(self.deleteContact)
        # Snip...

    def deleteContact(self):
        """Delete the selected contact from the database."""
        row = self.table.currentIndex().row()
        if row < 0:
            return

        messageBox = QMessageBox.warning(
            self,
            "Warning!",
            "Do you want to remove the selected contact?",
            QMessageBox.Ok | QMessageBox.Cancel,
        )

        if messageBox == QMessageBox.Ok:
            self.contactsModel.deleteContact(row)

In the first highlighted line, you connect the .clicked() signal of the Delete button to the .deleteContact() slot. This connection triggers a call to .deleteContact() every time the user clicks the button.

In .deleteContact() , you first get the index of the currently selected row in the table view. The if statement checks if the index is lower than 0 , which would mean that there are no contacts in the table view. If so, then the method returns immediately without performing any further actions.

Then the method shows a warning message confirming that the user wants to delete the selected contact. If the user accepts the operation, then .deleteContact(row) gets called. In this case, row represents the index of the currently selected row in the table.

After these additions, you can run the application again to get the following behavior:

Now when you select a contact from the table view and click Delete , you’re presented with a warning message. If you click the message dialog’s OK button, then the application removes the selected contact from the database, updating the table view accordingly.



Clearing the Contact Database

To remove all the contacts from the database, you’ll start by adding a method called .clearContacts() to ContactsModel . Open your model.py module and add the following method at the end of the class:

 1# -*- coding: utf-8 -*-
 2# rpcontacts/model.py
 3
 4# Snip...
 5class ContactsModel:
 6    # Snip...
 7
 8    def clearContacts(self):
 9        """Remove all contacts in the database."""
10        self.model.setEditStrategy(QSqlTableModel.OnManualSubmit)
11        self.model.removeRows(0, self.model.rowCount())
12        self.model.submitAll()
13        self.model.setEditStrategy(QSqlTableModel.OnFieldChange)
14        self.model.select()

Here’s what each line of code does:

  • Line 10 sets the data model’s .editStrategy property to QSqlTableModel.OnManualSubmit . This allows you to cache all the changes until you call .submitAll() later on. You need to do this because you’re changing several rows at the same time.
  • Line 11 removes all the rows from the model.
  • Line 12 saves changes to the database.
  • Line 13 resets the model’s .editStrategy property to its original value, QSqlTableModel.OnFieldChange . If you don’t reset this property to its original value, then you won’t be able to update the contacts directly in the table view.
  • Line 14 reloads the data into the model.

Once you’ve coded .clearContacts() , you can get back to the views.py file and update Window with the following code:

# -*- coding: utf-8 -*-
# rpcontacts/views.py

# Snip...
class Window(QMainWindow):
    # Snip...

    def setupUI(self):
        """Setup the main window's GUI."""
        # Snip...
        self.clearAllButton = QPushButton("Clear All")
        self.clearAllButton.clicked.connect(self.clearContacts)
        # Snip...

    def clearContacts(self):
        """Remove all contacts from the database."""
        messageBox = QMessageBox.warning(
            self,
            "Warning!",
            "Do you want to remove all your contacts?",
            QMessageBox.Ok | QMessageBox.Cancel,
        )

        if messageBox == QMessageBox.Ok:
            self.contactsModel.clearContacts()

The first highlighted line in this code connects the .clicked() signal of the Clear All button to the .clearContacts() slot below.

In .clearContacts() , you first create a message dialog, messageBox , to ask the user to confirm the removing operation. If the user confirms the operation by clicking OK , then .clearContacts() gets called on the model to remove all the contacts from the database:

That’s it! With this last piece of code, your contact book application is complete. The application provides features that allow your users to display, add, update, and remove contacts from the database.




Conclusion

Building a contact book GUI application with Python, PyQt, and SQLite is an excellent exercise for you to expand your skills with these tools and as a developer in general. Coding projects like this allows you to apply the knowledge and skills you already have and also pushes you to research and learn about new topics every time you encounter a new programming problem.

In this tutorial, you learned how to:

  • Build the GUI for a contact book application using PyQt
  • Use PyQt’s SQL support to connect the application to an SQLite database
  • Use PyQt’s Model-View architecture to work with the application’s database

You can download the complete source code for the contact book application and also the code to complete each step in this tutorial by clicking the link below:

Get the Source Code: Click here to get the source code you’ll use to build a contact book with Python, PyQt, and SQLite in this tutorial.



Next Steps

At this point, you’ve completed a fully functional contact book project. The application provides minimal functionality, but it’s a good starting point to continue adding features and take your Python and PyQt skills to the next level. Here are some next step ideas that you can implement:

  • Add new data fields: Adding new data fields to store more information about your contacts would be great. For example, you can add the contact’s photo, phone number, web page, Twitter handle, and so on. To do this, you might need to create new tables and set up relations between them. PyQt provides the QSqlRelationalTableModel , which defines an editable data model for a single table and provides foreign key support.

  • Provide search capability: Giving your users a way to search for a contact in the database is arguably a must-have feature in this kind of application. To implement it, you can use PyQt’s QSqlQuery and QSqlQueryModel .

  • Add back-up capability: Providing a way of backing up contact information is another interesting feature. Users might face problems with their computers and lose their data. You can provide options to upload the data to a cloud service or to back it up to an external disk.

These are just a few ideas for how you can continue adding features to your contact book. Take the challenge and build something amazing on top of this!



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQLite JSON_GROUP_OBJECT()

  2. Как мога да вмъкна изображение в sqlite база данни

  3. Как да коригирам URL адреса на доставчика на съдържание, който не е намерен в доставчика на съдържание за Android?

  4. Ограниченията на SQLite CHECK

  5. Как да активирате/деактивирате ограниченията на CHECK в SQLite