sql >> Databáze >  >> RDS >> SQLite

Sestavte si kontaktní knihu pomocí Pythonu, PyQt a SQLite

Stavební projekty jsou pravděpodobně jedním z nejdostupnějších a nejefektivnějších způsobů, jak se naučit programovat. Skutečné projekty vyžadují použití různých a rozmanitých dovedností kódování. Také vás vyzývají, abyste prozkoumali témata, která se objeví, když řešíte problémy v procesu vývoje. V tomto tutoriálu vytvoříte aplikaci kontaktní knihy s Pythonem, PyQt a SQLite.

V tomto kurzu se dozvíte, jak:

  • Vytvořte grafické uživatelské rozhraní (GUI) pro vaši aplikaci kontaktní knihy pomocí Pythonu a PyQt
  • Připojte aplikaci k databázi SQLite pomocí podpory SQL PyQt
  • Spravujte kontaktní údaje pomocí architektury Model-View PyQt

Na konci tohoto projektu budete mít funkční aplikaci s knihami kontaktů, která vám umožní ukládat a spravovat vaše kontaktní informace.

Chcete-li získat úplný zdrojový kód aplikace a také kód pro každý krok, kterým v tomto tutoriálu projdete, klikněte na odkaz níže:

Získejte zdrojový kód: Kliknutím sem získáte zdrojový kód, který v tomto tutoriálu použijete k vytvoření knihy kontaktů pomocí jazyků Python, PyQt a SQLite.


Ukázka:Kontaktní kniha s Pythonem

Knihy kontaktů jsou užitečným a široce používaným druhem aplikace. jsou všude. Pravděpodobně máte v telefonu a v počítači knihu kontaktů. Pomocí knihy kontaktů můžete ukládat a spravovat kontaktní informace členů své rodiny, přátel, spolupracovníků atd.

V tomto tutoriálu nakódujete GUI aplikaci pro knihu kontaktů pomocí Pythonu, SQLite a PyQt. Zde je ukázka toho, jak bude vaše kniha kontaktů vypadat a fungovat po provedení kroků v tomto tutoriálu:

Vaše kontaktní kniha poskytne minimální požadovanou sadu funkcí pro tento druh aplikace. Budete moci zobrazovat, vytvářet, aktualizovat a odstraňovat informace ve svém seznamu kontaktů.



Přehled projektu

Chcete-li vytvořit aplikaci kontaktní knihy, musíte kód uspořádat do modulů a balíčků a dát svému projektu koherentní strukturu. V tomto tutoriálu použijete následující strukturu adresářů a souborů:

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

Zde je stručný souhrn obsahu vašeho projektového adresáře:

  • rpcontacts_project/ je kořenový adresář projektu. Bude obsahovat následující soubory:
    • requirements.txt poskytuje seznam požadavků projektu.
    • README.md poskytuje obecné informace o projektu.
    • rpcontacts.py poskytuje skript vstupního bodu pro spuštění aplikace.
  • rpcontacts/ je podadresář, který poskytuje hlavní balíček aplikace. Poskytuje následující moduly:
    • __init__.py
    • views.py
    • database.py
    • main.py
    • model.py

Každý z těchto souborů krok za krokem proberete v tomto tutoriálu. Název každého souboru poskytuje představu o jeho roli v aplikaci. Například views.py bude obsahovat kód pro generování GUI oken a dialogů, database.py bude obsahovat kód pro práci s databází a main.py bude hostit samotnou aplikaci. Nakonec model.py implementuje model pro správu dat v databázi aplikace.

Obecně bude mít aplikace hlavní okno pro zobrazení, přidání, odstranění a aktualizaci kontaktů. Bude mít také dialogové okno pro přidání nových kontaktů do databáze.



Předpoklady

Chcete-li z tohoto projektu vytěžit maximum, pomohly by některé předchozí znalosti programování GUI s Pythonem a PyQt. V tomto ohledu budete potřebovat znát základy toho, jak:

  • Vytvářejte aplikace GUI pomocí PyQt a Python
  • Vytvářejte a rozmístěte GUI pomocí PyQt
  • Spravujte databáze SQL pomocí Pythonu a PyQt
  • Práce s databázemi SQLite

Chcete-li si tato témata oprášit, můžete se podívat na následující zdroje:

  • Python a PyQt:Vytvoření grafického uživatelského rozhraní pro stolní kalkulačku
  • Python a PyQt:Vytváření nabídek, panelů nástrojů a stavových pruhů
  • Rozvržení PyQt:Vytvářejte profesionálně vypadající GUI aplikace
  • Zacházení s databázemi SQL pomocí PyQt:Základy
  • Úvod do Python SQL knihoven
  • Správa dat pomocí Pythonu, SQLite a SQLAlchemy

Nebojte se, pokud nejste odborníkem v těchto oblastech, než začnete tento tutoriál. Naučíte se procesem ušpinění rukou na skutečném projektu. Pokud uvíznete, dejte si čas a projděte si výše uvedené zdroje. Pak se vraťte ke kódu.

Aplikace knihy kontaktů, kterou se chystáte vytvořit v tomto tutoriálu, má jedinou externí závislost:PyQt.

Poznámka: V tomto tutoriálu použijete PyQt verze 5.15.2 k vytvoření aplikace pro knihu kontaktů. Aby projekt fungoval na macOS Big Sur, je vyžadována verze 5.15.2.

PyQt verze 6.0 byla vydána 4. ledna 2021. Toto je první vydání knihovny, která se váže na Qt verzi 6. Projekt v tomto tutoriálu však nebyl testován s PyQt 6.0.

Pokud cítíte potřebu spustit projekt s touto novou verzí PyQt, zkuste to. Jako nápovědu byste měli pip install PyQt6 a poté aktualizujte importy tak, aby používaly PyQt6 místo PyQt5 .

Chcete-li ve svém vývojovém procesu dodržovat osvědčené postupy, můžete začít vytvořením virtuálního prostředí a následnou instalací PyQt pomocí pip . Jakmile nainstalujete PyQt, jste připraveni začít kódovat!



Krok 1:Vytvoření aplikace Skeleton knihy kontaktů pomocí PyQt

V tomto prvním kroku vytvoříte minimální, ale funkční aplikaci PyQt GUI, která poskytne základ, na kterém začnete budovat knihu kontaktů. Vytvoříte také minimální požadovanou strukturu projektu, včetně hlavního balíčku projektu a vstupního skriptu pro spuštění aplikace.

Veškerý kód a soubory, které přidáte do projektu kontaktní knihy v této sekci, jsou shromažďovány pod source_code_step_1/ adresář. Můžete si je stáhnout kliknutím na odkaz níže:

Získejte zdrojový kód: Kliknutím sem získáte zdrojový kód, který v tomto tutoriálu použijete k vytvoření knihy kontaktů pomocí jazyků Python, PyQt a SQLite.

Na konci této části budete moci poprvé spustit základní GUI aplikaci pro vaši knihu kontaktů.


Strukturování projektu Kontaktní knihy

Chcete-li začít kódovat aplikaci, pokračujte a vytvořte nový adresář s názvem rpcontacts_project/ . Toto bude kořenový adresář projektu. Nyní vytvořte nový podadresář s názvem rpcontacts/ uvnitř rpcontacts_project/ . Tento podadresář bude obsahovat hlavní balíček aplikace. Nakonec spusťte editor kódu nebo IDE v kořenovém adresáři.

Chcete-li změnit adresář na balíček, Python potřebuje __init__.py modul pro inicializaci balíčku. Vytvořte tento soubor v rpcontacts/ a přidejte do něj následující kód:

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

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

__version__ = "0.1.0"

Tento soubor říká Pythonu, že rpcontacts je balíček. Kód v souboru se spustí při importu balíčku nebo některých jeho modulů.

Do __init__.py nemusíte vkládat žádný kód soubor pro inicializaci balíčku. Prázdný __init__.py soubor udělá práci. V tomto případě však definujete konstantu na úrovni modulu s názvem __version__ k uložení čísla verze vaší aplikace.



Vytvoření hlavního okna aplikace

Nyní je čas vytvořit hlavní okno knihy kontaktů. Chcete-li to provést, vytvořte modul s názvem views.py ve vašich rpcontacts balík. Poté do modulu přidejte následující kód a uložte jej:

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

Nejprve importujete požadované třídy z PyQt5.QtWidgets . Poté vytvoříte Window . Tato třída dědí z QMainWindow a poskytuje kód pro vygenerování hlavního okna aplikace. V metodě inicializátoru nastavíte titulek okna na "RP Contacts" , změňte velikost okna na 550 podle 250 pixelů, definujte a nastavte centrální widget pomocí QWidget a nakonec definujte rozvržení pro centrální widget pomocí rozvržení vodorovného rámečku.



Kódování a spouštění aplikace

Protože již máte hlavní okno pro knihu kontaktů, je čas napsat kód pro vytvoření funkční aplikace PyQt pomocí QApplication . Chcete-li to provést, vytvořte nový modul s názvem main.py ve vašich rpcontacts balíček a přidejte do něj následující kód:

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

V tomto modulu importujete sys získat přístup k exit() , který umožňuje čisté ukončení aplikace, když uživatel zavře hlavní okno. Poté importujete QApplication z PyQt5.QtWidgets a Window z views . Posledním krokem je definování main() jako hlavní funkce vaší aplikace.

Uvnitř main() , vytvoříte instanci QApplication a Window . Potom zavoláte .show() v Window a nakonec spustíte hlavní smyčku aplikace nebo smyčka událostí pomocí .exec() .

Nyní přejděte nahoru do kořenového adresáře projektu rpcontacts_project/ a vytvořte soubor s názvem rpcontacts.py . Tento soubor poskytuje skript vstupního bodu pro spuštění aplikace. Přidejte do souboru následující kód a uložte jej:

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

Tento soubor importuje main() z vašeho main.py modul. Poté implementujete tradiční podmíněný příkaz, který volá main() pokud uživatel spustí tento modul jako skript Python. Nyní spusťte aplikaci spuštěním příkazu python rpcontacts.py ve vašem prostředí Pythonu. Na obrazovce se zobrazí následující okno:

A je to! Vytvořili jste minimální, ale funkční aplikaci PyQt GUI, kterou můžete použít jako výchozí bod pro vytvoření své knihy kontaktů. V tomto okamžiku by váš projekt měl mít následující strukturu:

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

V této části jste vytvořili minimální požadovanou strukturu pro svůj projekt kontaktní knihy pomocí modulů a balíčků Pythonu. Vytvořili jste hlavní okno aplikace a dali dohromady standardní kód pro vytvoření aplikace PyQt GUI. Aplikaci jste také spustili poprvé. Dále začnete přidávat funkce do svého GUI.




Krok 2:Vytvoření grafického uživatelského rozhraní knihy kontaktů pomocí Pythonu

Nyní, když jste vytvořili kostru aplikace knihy kontaktů, můžete začít kódovat GUI hlavního okna. Na konci této části provedete požadované kroky k vytvoření GUI vaší kontaktní knihy pomocí Pythonu a PyQt. GUI bude vypadat takto:

Uprostřed okna máte tabulkové zobrazení pro zobrazení seznamu kontaktů. Na pravé straně formuláře máte tři tlačítka:

  1. Přidat pro přidání nového kontaktu do seznamu
  2. Smazat pro odstranění vybraného kontaktu ze seznamu
  3. Vymazat vše pro odstranění všech kontaktů ze seznamu

Veškerý kód a soubory, které přidáte nebo upravíte v této sekci, jsou shromažďovány pod source_code_step_2/ adresář. Můžete si je stáhnout kliknutím na odkaz níže:

Získejte zdrojový kód: Kliknutím sem získáte zdrojový kód, který v tomto tutoriálu použijete k vytvoření knihy kontaktů pomocí jazyků Python, PyQt a SQLite.

Vraťte se na views.py modulu a aktualizujte kód Window pro vygenerování výše uvedeného 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)

Nejprve importujete nějaké další třídy PyQt, které chcete použít v GUI. Zde jsou některé z relevantnějších:

  • QPushButton vytvořte Přidat , Smazat a Vymazat vše tlačítka
  • QTableView poskytnout tabulkové zobrazení, které zobrazuje seznam kontaktů
  • QAbstractItemView poskytnout přístup k zásadám chování výběru zobrazení tabulky

V tomto kódu je první přídavek do Window je volání .setupUI() na konci __init__() . Toto volání vygeneruje GUI hlavního okna, když spustíte aplikaci.

Zde je kód v .setupUI() dělá:

  • Řádek 27 vytvoří QTableView k zobrazení seznamu kontaktů.
  • Řádek 28 nastavuje .selectionBehavior vlastnost na QAbstractItemView.SelectRows . Tím je zajištěno, že když uživatel klikne na kteroukoli buňku zobrazení tabulky, vybere se celý řádek. Řádky v zobrazení tabulky obsahují všechny informace související s jedním kontaktem v seznamu kontaktů.
  • Řádky 31 až 33 přidejte do GUI tři tlačítka:Přidat , Smazat a Vymazat vše . Tato tlačítka zatím neprovádějí žádné akce.
  • Řádky 35 až 41 vytvořit a nastavit koherentní rozvržení pro všechny widgety v GUI.

S těmito doplňky do Window , můžete aplikaci znovu spustit. Okno na vaší obrazovce bude vypadat jako okno, které jste viděli na začátku sekce.

Poznámka: Čísla řádků ve výše uvedeném kódu a ve zbývajících ukázkách kódu v tomto kurzu mají usnadnit vysvětlení. Neodpovídají pořadí řádků ve finálním modulu nebo skriptu.

V této části jste provedli všechny požadované kroky k vytvoření GUI hlavního okna knihy kontaktů. Nyní jste připraveni začít pracovat na tom, jak bude vaše aplikace spravovat a ukládat vaše kontaktní údaje.



Krok 3:Nastavení databáze seznamu kontaktů

V tomto okamžiku jste vytvořili aplikaci PyQt a její GUI hlavního okna pro vytvoření projektu knihy kontaktů. V této části napíšete kód, který definuje, jak se aplikace připojuje k databázi kontaktů. K dokončení tohoto kroku použijete SQLite pro správu databáze a podporu SQL PyQt pro připojení aplikace k databázi a pro práci s vašimi kontaktními údaji.

Zdrojový kód a soubory, které přidáte nebo upravíte v této sekci, jsou uloženy pod source_code_step_3/ adresář. Můžete si je stáhnout kliknutím na odkaz níže:

Získejte zdrojový kód: Kliknutím sem získáte zdrojový kód, který v tomto tutoriálu použijete k vytvoření knihy kontaktů pomocí jazyků Python, PyQt a SQLite.

Nejprve se vraťte na main.py v rpcontacts/ adresář a aktualizujte kód pro vytvoření připojení k databázi:

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

V tomto případě nejprve importujte createConnection() z database.py . Tato funkce bude obsahovat kód pro vytvoření a otevření připojení k databázi kontaktů. Vytvoříte database.py a napište createConnection() v další části.

Uvnitř main() , první zvýrazněný řádek je pokus o vytvoření připojení k databázi pomocí createConnection() . Pokud z nějakého důvodu aplikace není schopna vytvořit připojení, zavolá se sys.exit(1) zavře aplikaci bez vytvoření grafického prvku a bude indikovat, že došlo k chybě.

S připojením musíte zacházet tímto způsobem, protože aplikace závisí na databázi, aby správně fungovala. Pokud nemáte funkční připojení, vaše aplikace nebude fungovat vůbec.

Tento postup vám umožňuje ošetřit chyby a v případě problému zcela zavřít aplikaci. Také budete moci uživateli poskytnout relevantní informace o chybě, na kterou aplikace narazila při pokusu o připojení k databázi.

S těmito doplňky je čas ponořit se do kódu createConnection() .


Připojení k databázi pomocí PyQt a SQLite

Základním krokem při vývoji aplikace je připojení aplikace knihy kontaktů k její přidružené databázi. Chcete-li to provést, nakódujte funkci nazvanou createConnection() , který vytvoří a otevře připojení k databázi. Pokud je připojení úspěšné, funkce vrátí True . V opačném případě poskytne informace o příčině selhání připojení.

Vraťte se na rpcontacts/ adresář a vytvořte nový modul s názvem database.py v něm. Poté do tohoto modulu přidejte následující kód:

 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

Zde nejprve importujete některé požadované třídy PyQt. Poté definujete createConnection() . Tato funkce má jeden argument:databaseName obsahuje název nebo cestu k fyzickému souboru databáze SQLite ve vašem systému souborů.

Zde je kód uvnitř createConnection() dělá:

  • Řádek 11 vytvoří připojení k databázi pomocí QSQLITE řidič.
  • Řádek 12 nastavuje název souboru nebo cestu k databázi.
  • Řádek 14 pokusí o otevření spojení. Pokud dojde k problému během volání .open() a poté if blok kódu zobrazí chybovou zprávu a poté vrátí False označující, že pokus o připojení selhal.
  • Řádek 22 vrátí True pokud je pokus o připojení úspěšný.

Již jste zakódovali createConnection() . Nyní můžete napsat kód pro vytvoření contacts tabulky v databázi.



Vytvoření contacts Tabulka

Se zavedenou funkcí, která vytváří a otevírá připojení k databázi, můžete přistoupit ke kódování pomocné funkce pro vytvoření contacts stůl. Tuto tabulku použijete k uložení informací o svých kontaktech.

Zde je kód, který 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

Zde nejprve přidáte nový import. Importujete QSqlQuery k provádění a manipulaci s příkazy SQL.

Uvnitř _createContactsTable() , vytvoříte QSqlQuery instance. Potom zavoláte .exec() na objekt dotazu pomocí řetězce SQL CREATE TABLE prohlášení jako argument. Tento příkaz vytvoří novou tabulku nazvanou contacts ve vaší databázi. Tabulka má následující sloupce:

Sloupec Obsah
id Celé číslo s primárním klíčem tabulky
name Řetězec se jménem kontaktu
job Řetězec s pracovním názvem kontaktu
email Řetězec s e-mailem kontaktu

contacts tabulka ve vaší databázi bude ukládat relevantní informace o vašich kontaktech.

Poslední krok k dokončení kódování database.py je přidat volání do _createContactsTable() zevnitř createConnection() , těsně před posledním return prohlášení. To zajistí, že aplikace vytvoří contacts před provedením jakékoli operace s databází.

Jakmile vytvoříte contacts tabulky, můžete na databázi spustit nějaké testy a také přidat nějaká ukázková data pro další testování.



Testování databáze knihy kontaktů

Zatím jste dokončili psaní požadovaného kódu pro zpracování připojení k databázi kontaktů. V této části provedete několik testů, abyste se ujistili, že tento kód a samotná databáze fungují správně. Do databáze také přidáte některá ukázková data, abyste mohli později v tomto kurzu provést další testování.

Nyní otevřete terminál nebo příkazový řádek a přejděte do kořenového adresáře projektu, rpcontacts_project/ . Jakmile tam budete, spusťte interaktivní relaci Pythonu a zadejte následující kód:

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

Zde nejprve importujte createConnection() z database.py modul. Poté zavoláte tuto funkci pro vytvoření a otevření připojení k databázi kontaktů. Název databáze je contacts.sqlite . Protože tento soubor v kořenovém adresáři projektu neexistuje, SQLite jej vytvoří za vás. Můžete to zkontrolovat, když se podíváte do svého aktuálního adresáře.

Dále potvrdíte, že databáze obsahuje tabulku nazvanou contacts . Chcete-li to provést, zavoláte .database() na QSqlDatabase . Tato metoda třídy vrací ukazatel na aktuální připojení k databázi. S tímto odkazem na připojení můžete volat .tables() získat seznam tabulek v databázi. Všimněte si, že první tabulka v seznamu je contacts , takže teď máte jistotu, že vše funguje dobře.

Nyní můžete připravit SQL dotaz pro vložení ukázkových dat do contacts tabulka:

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

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

Výše uvedený dotaz umožňuje vložit konkrétní hodnoty do name , job a email atributy a uložit tyto hodnoty do databáze. Níže je uveden příklad, jak to provést:

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

V této části kódu nejprve definujete data uchovávat kontaktní informace seznamu lidí. Dále použijete for smyčka pro vložení dat voláním .addBindValue() . Potom zavoláte .exec() na objekt dotazu, aby bylo možné efektivně spustit dotaz SQL na databázi.

Protože všechna volání .exec() vrátí True , můžete dojít k závěru, že data byla úspěšně vložena do databáze. Pokud to chcete potvrdit, spusťte následující kód:

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

A je to! Vaše databáze funguje dobře! Nyní máte několik ukázkových dat k testování aplikace a můžete se soustředit na to, jak načíst a zobrazit kontaktní informace v hlavním okně knihy kontaktů.




Krok 4:Zobrazení a aktualizace existujících kontaktů

Chcete-li zobrazit svá kontaktní data v hlavním okně aplikace, můžete použít QTableView . Tato třída je součástí architektury Model-View PyQt a poskytuje robustní a efektivní způsob zobrazení položek z objektu modelu PyQt.

Soubory a kód, který přidáte nebo upravíte v této sekci, jsou uloženy pod source_code_step_4/ adresář. Chcete-li si je stáhnout, klikněte na odkaz níže:

Získejte zdrojový kód: Kliknutím sem získáte zdrojový kód, který v tomto tutoriálu použijete k vytvoření knihy kontaktů pomocí jazyků Python, PyQt a SQLite.

Po dokončení tohoto kroku bude vaše kniha kontaktů vypadat takto:

Objekt zobrazení tabulky v hlavním okně poskytuje požadovanou funkcionalitu, která vám umožní rychle upravit a aktualizovat kontaktní informace.

Chcete-li například aktualizovat jméno kontaktu, můžete dvakrát kliknout na buňku obsahující jméno, aktualizovat jméno a poté stisknout Enter pro automatické uložení změn do databáze. Než to však budete moci udělat, musíte vytvořit model a připojit jej k zobrazení tabulky.


Vytvoření modelu pro zpracování kontaktních dat

PyQt poskytuje bohatou sadu tříd pro práci s databázemi SQL. Pro aplikaci knihy kontaktů použijete QSqlTableModel , který poskytuje upravitelný datový model pro jednu databázovou tabulku. Pro tuto práci je ideální, protože vaše databáze má jedinou tabulku contacts .

Vraťte se do editoru kódu a vytvořte nový modul s názvem model.py uvnitř rpcontacts/ adresář. Přidejte do souboru následující kód a uložte jej:

 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

V tomto kódu nejprve provedete požadované importy a poté vytvoříte ContactsModel . V inicializátoru třídy definujete atribut instance s názvem .model k uložení datového modelu.

Dále přidáte statickou metodu pro vytvoření a nastavení objektu modelu. 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/ adresář. 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/ adresář. 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() později. 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:

A je to! 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. Může být cizí klíč NULL a/nebo duplicitní?

  2. Jak opravit chybu Microsoft SQL Server 926?- Vyřešeno

  3. Základy tabulkových výrazů, 1. část

  4. Mapování cizího klíče s vlastním názvem sloupce