SQLite
 sql >> Baza danych >  >> RDS >> SQLite

Zbuduj książkę kontaktów za pomocą Pythona, PyQt i SQLite

Tworzenie projektów jest prawdopodobnie jednym z bardziej przystępnych i skutecznych sposobów uczenia się programowania. Prawdziwe projekty wymagają zastosowania różnych i zróżnicowanych umiejętności kodowania. Zachęcają również do badania tematów, które pojawiają się podczas rozwiązywania problemów w procesie rozwoju. W tym samouczku utworzysz aplikację książki kontaktowej za pomocą Pythona, PyQt i SQLite.

W tym samouczku dowiesz się, jak:

  • Utwórz graficzny interfejs użytkownika (GUI) dla Twojej aplikacji książki kontaktów przy użyciu Pythona i PyQt
  • Połącz aplikację z bazą danych SQLite przy użyciu obsługi SQL PyQt
  • Zarządzaj danymi kontaktowymi za pomocą architektury Model-View PyQt

Pod koniec tego projektu będziesz mieć funkcjonalną aplikację książki kontaktów, która pozwoli Ci przechowywać i zarządzać informacjami kontaktowymi.

Aby uzyskać pełny kod źródłowy aplikacji, a także kod dla każdego kroku, który przejdziesz w tym samouczku, kliknij poniższy link:

Pobierz kod źródłowy: Kliknij tutaj, aby uzyskać kod źródłowy, którego użyjesz do zbudowania książki kontaktów z Python, PyQt i SQLite w tym samouczku.


Demo:Książka kontaktowa z Pythonem

Książki kontaktowe są użytecznym i szeroko stosowanym rodzajem aplikacji. Są wszędzie. Prawdopodobnie masz książkę kontaktów w telefonie i na komputerze. Dzięki książce kontaktów możesz przechowywać informacje kontaktowe członków rodziny, przyjaciół, współpracowników itd. i zarządzać nimi.

W tym samouczku zakodujesz aplikację GUI książki kontaktów za pomocą Pythona, SQLite i PyQt. Oto demonstracja wyglądu i działania Twojej książki kontaktów po wykonaniu czynności opisanych w tym samouczku:

Twoja książka kontaktowa zapewni minimalny zestaw funkcji wymaganych dla tego rodzaju aplikacji. Będziesz mógł wyświetlać, tworzyć, aktualizować i usuwać informacje ze swojej listy kontaktów.



Przegląd projektu

Aby zbudować swoją aplikację książki kontaktów, musisz uporządkować kod w moduły i pakiety oraz nadać projektowi spójną strukturę. W tym samouczku użyjesz następujących katalogów i struktury plików:

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

Oto krótkie podsumowanie zawartości katalogu twojego projektu:

  • rpcontacts_project/ to katalog główny projektu. Będzie zawierać następujące pliki:
    • requirements.txt udostępnia listę wymagań projektu.
    • README.md zawiera ogólne informacje o projekcie.
    • rpcontacts.py dostarcza skrypt punktu wejścia do uruchomienia aplikacji.
  • rpcontacts/ to podkatalog dostarczający główny pakiet aplikacji. Zawiera następujące moduły:
    • __init__.py
    • views.py
    • database.py
    • main.py
    • model.py

W tym samouczku omówisz każdy z tych plików krok po kroku. Nazwa każdego pliku daje wyobrażenie o jego roli w aplikacji. Na przykład views.py będzie zawierał kod do generowania GUI okien i okien dialogowych, database.py będzie zawierał kod do pracy z bazą danych oraz main.py będzie hostować samą aplikację. Wreszcie model.py wdroży model do zarządzania danymi w bazie danych aplikacji.

Ogólnie aplikacja będzie miała główne okno do wyświetlania, dodawania, usuwania i aktualizowania kontaktów. Będzie również zawierać okno dialogowe dodawania nowych kontaktów do bazy danych.



Wymagania wstępne

Aby jak najlepiej wykorzystać ten projekt, pomocna byłaby wcześniejsza znajomość programowania GUI w Pythonie i PyQt. W związku z tym musisz znać podstawy, jak:

  • Twórz aplikacje GUI za pomocą PyQt i Pythona
  • Buduj i rozmieszczaj GUI za pomocą PyQt
  • Zarządzaj bazami danych SQL za pomocą Pythona i PyQt
  • Pracuj z bazami danych SQLite

Aby odświeżyć te tematy, możesz zapoznać się z następującymi zasobami:

  • Python i PyQt:tworzenie kalkulatora graficznego GUI
  • Python i PyQt:tworzenie menu, pasków narzędzi i pasków stanu
  • Układy PyQt:Twórz profesjonalne aplikacje GUI
  • Obsługa baz danych SQL za pomocą PyQt:podstawy
  • Wprowadzenie do bibliotek Pythona SQL
  • Zarządzanie danymi za pomocą Pythona, SQLite i SQLAlchemy

Nie martw się, jeśli nie jesteś ekspertem w tych dziedzinach przed rozpoczęciem tego samouczka. Dowiesz się, jak ubrudzić sobie ręce przy prawdziwym projekcie. Jeśli utkniesz, nie spiesz się i przejrzyj zasoby, do których prowadzą linki powyżej. Następnie wróć do kodu.

Aplikacja książki kontaktów, którą zamierzasz zbudować w tym samouczku, ma jedną zewnętrzną zależność:PyQt.

Uwaga: W tym samouczku użyjesz PyQt w wersji 5.15.2 do zbudowania aplikacji książki kontaktowej. Wersja 5.15.2 jest wymagana, aby projekt działał na macOS Big Sur.

PyQt w wersji 6.0 zostało wydane 4 stycznia 2021 r. Jest to pierwsze wydanie biblioteki, która wiąże się z Qt w wersji 6. Jednak projekt w tym samouczku nie był testowany z PyQt 6.0.

Jeśli czujesz potrzebę uruchomienia projektu z nową wersją PyQt, spróbuj. Jako wskazówkę, powinieneś pip install PyQt6 a następnie zaktualizuj importy, aby używały PyQt6 zamiast PyQt5 .

Aby postępować zgodnie z najlepszymi praktykami w procesie rozwoju, możesz zacząć od stworzenia środowiska wirtualnego, a następnie zainstalowania PyQt przy użyciu pip . Po zainstalowaniu PyQt możesz zacząć kodować!



Krok 1:Tworzenie aplikacji szkieletu książki kontaktów za pomocą PyQt

W tym pierwszym kroku stworzysz minimalną, ale funkcjonalną aplikację GUI PyQt, która zapewni podstawę, na której zaczniesz budować książkę kontaktów. Utworzysz również minimalną wymaganą strukturę projektu, w tym główny pakiet projektu i skrypt wejściowy do uruchomienia aplikacji.

Cały kod i pliki, które dodasz do projektu książki kontaktów w tej sekcji, są gromadzone w sekcji source_code_step_1/ informator. Możesz je pobrać, klikając poniższy link:

Pobierz kod źródłowy: Kliknij tutaj, aby uzyskać kod źródłowy, którego użyjesz do zbudowania książki kontaktów z Python, PyQt i SQLite w tym samouczku.

Pod koniec tej sekcji będziesz mógł po raz pierwszy uruchomić szkieletową aplikację GUI dla swojej książki kontaktowej.


Strukturyzacja projektu książki kontaktowej

Aby rozpocząć kodowanie aplikacji, stwórz nowy katalog o nazwie rpcontacts_project/ . Będzie to katalog główny projektu. Teraz utwórz nowy podkatalog o nazwie rpcontacts/ wewnątrz rpcontacts_project/ . Ten podkatalog będzie zawierał główny pakiet aplikacji. Na koniec uruchom edytor kodu lub IDE w katalogu głównym.

Aby zmienić katalog w pakiet, Python potrzebuje __init__.py moduł do inicjalizacji pakietu. Utwórz ten plik w rpcontacts/ i dodaj do niego następujący kod:

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

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

__version__ = "0.1.0"

Ten plik mówi Pythonowi, że rpcontacts to pakiet. Kod w pliku jest uruchamiany podczas importowania pakietu lub niektórych jego modułów.

Nie musisz umieszczać żadnego kodu w __init__.py plik, aby zainicjować pakiet. Pusty __init__.py plik wykona zadanie. Jednak w tym przypadku definiujesz stałą na poziomie modułu o nazwie __version__ do przechowywania numeru wersji Twojej aplikacji.



Tworzenie głównego okna aplikacji

Teraz nadszedł czas, aby utworzyć główne okno swojej książki kontaktowej. Aby to zrobić, utwórz moduł o nazwie views.py w Twoich rpcontacts pakiet. Następnie dodaj następujący kod do modułu i zapisz go:

# -*- 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)

Najpierw importujesz wymagane klasy z PyQt5.QtWidgets . Następnie tworzysz Window . Ta klasa dziedziczy z QMainWindow i dostarcza kod do wygenerowania głównego okna aplikacji. W metodzie inicjującej ustaw tytuł okna na "RP Contacts" , zmień rozmiar okna na 550 przez 250 pikseli, zdefiniuj i ustaw centralny widżet za pomocą QWidget , a na koniec zdefiniuj układ centralnego widżetu, używając poziomego układu prostokątnego.



Kodowanie i uruchamianie aplikacji

Ponieważ masz już główne okno książki kontaktów, czas napisać kod do tworzenia funkcjonalnej aplikacji PyQt za pomocą QApplication . Aby to zrobić, utwórz nowy moduł o nazwie main.py w Twoich rpcontacts pakiet i dodaj do niego następujący kod:

# -*- 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())

W tym module importujesz sys aby uzyskać dostęp do exit() , co pozwala na czyste wyjście z aplikacji, gdy użytkownik zamknie okno główne. Następnie importujesz QApplication z PyQt5.QtWidgets i Window z views . Ostatnim krokiem jest zdefiniowanie main() jako główna funkcja Twojej aplikacji.

Wewnątrz main() , tworzysz instancję QApplication i Window . Następnie wywołujesz .show() w Window , a na koniec uruchamiasz główną pętlę aplikacji lub pętla zdarzeń , używając .exec() .

Teraz przejdź do katalogu głównego projektu rpcontacts_project/ i utwórz plik o nazwie rpcontacts.py . Ten plik zawiera skrypt punktu wejścia do uruchamiania aplikacji. Dodaj następujący kod do pliku i zapisz go:

#!/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()

Ten plik importuje main() z Twojego main.py moduł. Następnie implementujesz tradycyjną instrukcję warunkową, która wywołuje main() jeśli użytkownik uruchomi ten moduł jako skrypt Pythona. Teraz uruchom aplikację, uruchamiając polecenie python rpcontacts.py w twoim środowisku Pythona. Na ekranie pojawi się następujące okno:

Otóż ​​to! Stworzyłeś minimalną, ale funkcjonalną aplikację GUI PyQt, której możesz użyć jako punktu wyjścia do zbudowania swojej książki kontaktowej. W tym momencie Twój projekt powinien mieć następującą strukturę:

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

W tej sekcji utworzyłeś minimalną wymaganą strukturę dla swojego projektu książki kontaktowej za pomocą modułów i pakietów Pythona. Zbudowałeś główne okno aplikacji i ułożyłeś kod wzorcowy, aby utworzyć aplikację GUI PyQt. Uruchomiłeś też aplikację po raz pierwszy. Następnie zaczniesz dodawać funkcje do swojego GUI.




Krok 2:Budowanie graficznego interfejsu użytkownika książki kontaktów za pomocą Pythona

Po zbudowaniu szkieletu aplikacji książki kontaktów możesz zacząć kodować GUI głównego okna. Na końcu tej sekcji wykonasz wymagane kroki, aby utworzyć GUI swojej książki kontaktowej za pomocą Pythona i PyQt. GUI będzie wyglądać tak:

W środku okna masz widok tabeli, w którym wyświetlana jest lista kontaktów. Po prawej stronie formularza znajdują się trzy przyciski:

  1. Dodaj dodać nowy kontakt do listy
  2. Usuń aby usunąć wybrany kontakt z listy
  3. Wyczyść wszystko aby usunąć wszystkie kontakty z listy

Cały kod i pliki, które dodasz lub zmodyfikujesz w tej sekcji, są gromadzone w sekcji source_code_step_2/ informator. Możesz je pobrać, klikając poniższy link:

Pobierz kod źródłowy: Kliknij tutaj, aby uzyskać kod źródłowy, którego użyjesz do zbudowania książki kontaktów z Python, PyQt i SQLite w tym samouczku.

Wróć do views.py i zaktualizuj kod Window aby wygenerować powyższy 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)

Najpierw importujesz dodatkowe klasy PyQt do użycia w GUI. Oto niektóre z bardziej odpowiednich:

  • QPushButton aby utworzyć Dodaj , Usuń i Wyczyść wszystko przyciski
  • QTableView aby zapewnić widok podobny do tabeli, który wyświetla listę kontaktów
  • QAbstractItemView aby zapewnić dostęp do zasad zachowania wyboru widoku tabeli

W tym kodzie pierwszy dodatek do Window jest wywołaniem .setupUI() na końcu __init__() . To wywołanie generuje GUI głównego okna po uruchomieniu aplikacji.

Oto kod wewnątrz .setupUI() robi:

  • Linia 27 tworzy QTableView wystąpienie, aby wyświetlić listę kontaktów.
  • Linia 28 ustawia .selectionBehavior właściwość QAbstractItemView.SelectRows . Gwarantuje to, że gdy użytkownik kliknie dowolną komórkę w widoku tabeli, zostanie wybrany cały wiersz. Wiersze w widoku tabeli zawierają wszystkie informacje związane z pojedynczym kontaktem na liście kontaktów.
  • Linie 31 do 33 dodaj trzy przyciski do GUI:Dodaj , Usuń i Wyczyść wszystko . Te przyciski nie wykonują jeszcze żadnych działań.
  • Linie od 35 do 41 stwórz i ustaw spójny układ dla wszystkich widżetów w GUI.

Z tymi dodatkami do Window , możesz ponownie uruchomić aplikację. Okno na ekranie będzie wyglądać jak okno, które widziałeś na początku sekcji.

Uwaga: Numery wierszy w powyższym kodzie iw pozostałych przykładach kodu w tym samouczku mają na celu ułatwienie wyjaśnienia. Nie pasują do kolejności wierszy w końcowym module lub skrypcie.

W tej sekcji wykonałeś wszystkie wymagane kroki, aby utworzyć GUI w głównym oknie książki kontaktów. Możesz teraz rozpocząć pracę nad sposobem, w jaki Twoja aplikacja będzie zarządzać Twoimi danymi kontaktowymi i przechowywać je.



Krok 3:Konfigurowanie bazy danych książki kontaktów

W tym momencie utworzyłeś aplikację PyQt i jej GUI w głównym oknie, aby zbudować swój projekt książki kontaktowej. W tej sekcji napiszesz kod określający, w jaki sposób aplikacja łączy się z bazą danych kontaktów. Aby wykonać ten krok, użyjesz SQLite do obsługi bazy danych i obsługi SQL PyQt, aby połączyć aplikację z bazą danych i pracować z danymi kontaktowymi.

Kod źródłowy i pliki, które dodasz lub zmodyfikujesz w tej sekcji, są przechowywane w sekcji source_code_step_3/ informator. Możesz je pobrać, klikając poniższy link:

Pobierz kod źródłowy: Kliknij tutaj, aby uzyskać kod źródłowy, którego użyjesz do zbudowania książki kontaktów z Python, PyQt i SQLite w tym samouczku.

Najpierw wróć do main.py w rpcontacts/ katalogu i zaktualizuj kod, aby utworzyć połączenie z bazą danych:

# -*- 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_())

W takim przypadku najpierw importujesz createConnection() z database.py . Ta funkcja będzie zawierała kod do utworzenia i otwarcia połączenia z bazą kontaktów. Utworzysz database.py i napisz createConnection() w następnej sekcji.

Wewnątrz main() , pierwsza podświetlona linia to próba nawiązania połączenia z bazą danych za pomocą createConnection() . Jeśli z jakiegoś powodu aplikacja nie może nawiązać połączenia, wywołaj sys.exit(1) zamknie aplikację bez tworzenia elementu graficznego i wskaże, że wystąpił błąd.

Musisz obsłużyć połączenie w ten sposób, ponieważ aplikacja zależy od bazy danych, aby działała poprawnie. Jeśli nie masz działającego połączenia, Twoja aplikacja w ogóle nie będzie działać.

Ta praktyka umożliwia obsługę błędów i czyste zamknięcie aplikacji w przypadku wystąpienia problemu. Będziesz także mógł przedstawić użytkownikowi istotne informacje o błędzie, który napotkała aplikacja podczas próby połączenia z bazą danych.

Po wprowadzeniu tych dodatków nadszedł czas, aby zagłębić się w kod createConnection() .


Łączenie się z bazą danych za pomocą PyQt i SQLite

Połączenie aplikacji książki kontaktów z skojarzoną z nią bazą danych jest podstawowym krokiem w rozwoju aplikacji. Aby to zrobić, zakodujesz funkcję o nazwie createConnection() , który utworzy i otworzy połączenie z bazą danych. Jeśli połączenie się powiedzie, funkcja zwróci True . W przeciwnym razie dostarczy informacji o przyczynie niepowodzenia połączenia.

Wróć do rpcontacts/ katalogu i utwórz nowy moduł o nazwie database.py w nim. Następnie dodaj następujący kod do tego modułu:

 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

Tutaj najpierw importujesz niektóre wymagane klasy PyQt. Następnie definiujesz createConnection() . Ta funkcja przyjmuje jeden argument:databaseName przechowuje nazwę lub ścieżkę do fizycznego pliku bazy danych SQLite w twoim systemie plików.

Oto kod wewnątrz createConnection() robi:

  • Linia 11 tworzy połączenie z bazą danych za pomocą QSQLITE kierowca.
  • Linia 12 ustawia nazwę pliku lub ścieżkę do bazy danych.
  • Linia 14 próbuje otworzyć połączenie. Jeśli wystąpi problem podczas wywołania .open() , a następnie if blok kodu wyświetla komunikat o błędzie, a następnie zwraca False aby wskazać, że próba połączenia nie powiodła się.
  • Linia 22 zwraca True jeśli próba połączenia się powiedzie.

Już zakodowałeś createConnection() . Teraz możesz napisać kod, aby utworzyć contacts tabele w bazie danych.



Tworzenie contacts Tabela

Dzięki funkcji, która tworzy i otwiera połączenie z bazą danych, możesz przejść do kodowania funkcji pomocniczej, aby utworzyć contacts stół. Użyjesz tej tabeli do przechowywania informacji o swoich kontaktach.

Oto kod, który implementuje _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

Tutaj najpierw dodajesz nowy import. Importujesz QSqlQuery do wykonywania i manipulowania instrukcjami SQL.

Wewnątrz _createContactsTable() , tworzysz QSqlQuery instancja. Następnie wywołujesz .exec() na obiekcie zapytania za pomocą opartego na ciągach kodu SQL CREATE TABLE oświadczenie jako argument. Ta instrukcja tworzy nową tabelę o nazwie contacts w Twojej bazie danych. Tabela ma następujące kolumny:

Kolumna Treść
id Liczba całkowita z kluczem podstawowym tabeli
name Ciąg z nazwą kontaktu
job Ciąg z nazwą stanowiska osoby kontaktowej
email Ciąg z adresem e-mail kontaktu

contacts tabela w Twojej bazie danych będzie przechowywać istotne informacje o Twoich kontaktach.

Ostatni krok do zakończenia kodowania database.py jest dodanie wywołania do _createContactsTable() od wewnątrz createConnection() , tuż przed ostatnim return oświadczenie. Dzięki temu aplikacja utworzy contacts tabeli przed wykonaniem jakichkolwiek operacji na bazie danych.

Po utworzeniu contacts tabeli, możesz uruchomić kilka testów w bazie danych, a także dodać kilka przykładowych danych do dalszych testów.



Testowanie bazy danych książki kontaktów

Do tej pory zakończyłeś pisanie wymaganego kodu do obsługi połączenia z bazą danych książki kontaktów. W tej sekcji wykonasz kilka testów, aby upewnić się, że ten kod i sama baza danych działają poprawnie. Dodasz także kilka przykładowych danych do bazy danych, aby przeprowadzić dalsze testy w dalszej części tego samouczka.

Teraz otwórz terminal lub wiersz poleceń i przejdź do katalogu głównego projektu, rpcontacts_project/ . Tam uruchom interaktywną sesję Pythona i wpisz następujący kod:

>>>
>>> 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']

Tutaj najpierw importujesz createConnection() z database.py moduł. Następnie wywołujesz tę funkcję, aby utworzyć i otworzyć połączenie z bazą kontaktów. Nazwa pliku bazy danych to contacts.sqlite . Ponieważ ten plik nie istnieje w katalogu głównym projektu, SQLite utworzy go za Ciebie. Możesz to sprawdzić, zaglądając do swojego bieżącego katalogu.

Następnie potwierdzasz, że baza danych zawiera tabelę o nazwie contacts . Aby to zrobić, wywołujesz .database() na QSqlDatabase . Ta metoda klasy zwraca wskaźnik do bieżącego połączenia z bazą danych. Z tym odniesieniem do połączenia możesz wywołać .tables() aby uzyskać listę tabel w bazie danych. Zauważ, że pierwsza tabela na liście to contacts , więc teraz masz pewność, że wszystko działa dobrze.

Teraz możesz przygotować zapytanie SQL, aby wstawić przykładowe dane do contacts tabela:

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

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

Powyższe zapytanie pozwala wstawić określone wartości do name , job i email atrybuty i zapisać te wartości w bazie danych. Poniżej znajduje się przykład, jak to zrobić:

>>>
>>> # 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

W tym fragmencie kodu najpierw definiujesz data przechowywać informacje kontaktowe listy osób. Następnie użyj for pętla, aby wstawić dane, wywołując .addBindValue() . Następnie wywołujesz .exec() na obiekcie zapytania, aby skutecznie uruchomić zapytanie SQL w bazie danych.

Ponieważ wszystkie wywołania .exec() zwróć True , można stwierdzić, że dane zostały pomyślnie wprowadzone do bazy danych. Jeśli chcesz to potwierdzić, uruchom następujący kod:

>>>
>>> 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]

Otóż ​​to! Twoja baza danych działa dobrze! Teraz masz kilka przykładowych danych do przetestowania aplikacji i możesz skupić się na ładowaniu i wyświetlaniu informacji kontaktowych w głównym oknie książki kontaktów.




Krok 4:Wyświetlanie i aktualizowanie istniejących kontaktów

Aby wyświetlić swoje dane kontaktowe w głównym oknie aplikacji, możesz użyć QTableView . Ta klasa jest częścią architektury Model-View PyQt i zapewnia solidny i wydajny sposób wyświetlania elementów z obiektu modelu PyQt.

Pliki i kod, które dodasz lub zmodyfikujesz w tej sekcji, są przechowywane w sekcji source_code_step_4/ informator. Aby je pobrać, kliknij poniższy link:

Pobierz kod źródłowy: Kliknij tutaj, aby uzyskać kod źródłowy, którego użyjesz do zbudowania książki kontaktów z Python, PyQt i SQLite w tym samouczku.

Po zakończeniu tego kroku Twoja książka kontaktów będzie wyglądać tak:

Obiekt widoku tabeli w głównym oknie zapewnia wymaganą funkcjonalność umożliwiającą szybką modyfikację i aktualizację informacji kontaktowych.

Na przykład, aby zaktualizować nazwę kontaktu, możesz dwukrotnie kliknąć komórkę zawierającą tę nazwę, zaktualizować nazwę, a następnie nacisnąć Enter aby automatycznie zapisać zmiany w bazie danych. Ale zanim będziesz mógł to zrobić, musisz utworzyć model i połączyć go z widokiem tabeli.


Tworzenie modelu do obsługi danych kontaktowych

PyQt zapewnia bogaty zestaw klas do pracy z bazami danych SQL. W swojej aplikacji książki kontaktowej użyjesz QSqlTableModel , który zapewnia edytowalny model danych dla pojedynczej tabeli bazy danych. Jest idealny do pracy, ponieważ Twoja baza danych ma jedną tabelę, contacts .

Wróć do edytora kodu i utwórz nowy moduł o nazwie model.py wewnątrz rpcontacts/ informator. Dodaj następujący kod do pliku i zapisz go:

 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

W tym kodzie najpierw wykonujesz wymagane importy, a następnie tworzysz ContactsModel . In the class initializer, you define an instance attribute called .model to hold the data 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 pole. 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/ directory. 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/ directory. 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. Aktualizacja SQLite

  2. Emulator a pamięć karty SD urządzenia Samsung

  3. Wyświetl wszystkie tabele tymczasowe w SQLite

  4. Jak zawijać długie wiersze tekstu w wynikach SQLite

  5. zapisz List<Model class> do sqlite