Skip to content

Commit 7e80569

Browse files
committed
add crud app pyqt5 tutorial
1 parent 8b0c1bb commit 7e80569

File tree

5 files changed

+203
-0
lines changed

5 files changed

+203
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ This is a repository of all the tutorials of [The Python Code](https://www.thepy
289289
- [How to Make a Real-Time GUI Spelling Checker in Python](https://www.thepythoncode.com/article/make-a-realtime-spelling-checker-gui-python). ([code](gui-programming/realtime-spelling-checker))
290290
- [How to Build a GUI Language Translator App in Python](https://www.thepythoncode.com/article/build-a-gui-language-translator-tkinter-python). ([code](gui-programming/gui-language-translator))
291291
- [How to Make an Image Editor in Python](https://www.thepythoncode.com/article/make-an-image-editor-in-tkinter-python). ([code](gui-programming/image-editor))
292+
- [How to Build a CRUD App with PyQt5 and SQLite3 in Python](https://thepythoncode.com/article/build-a-crud-app-using-pyqt5-and-sqlite3-in-python). ([code](gui-programming/crud-app-pyqt5))
292293

293294
- ### [Game Development](https://www.thepythoncode.com/topic/game-development)
294295
- [How to Make a Button using PyGame in Python](https://www.thepythoncode.com/article/make-a-button-using-pygame-in-python). ([code](gui-programming/button-in-pygame))
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# [How to Build a CRUD App with PyQt5 and SQLite3 in Python](https://thepythoncode.com/article/build-a-crud-app-using-pyqt5-and-sqlite3-in-python)

gui-programming/crud-app-pyqt5/db.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import sqlite3
2+
import datetime
3+
4+
5+
def create_table():
6+
db = sqlite3.connect('database.db')
7+
query = """
8+
CREATE TABLE if not exists BOOKS
9+
(ID INTEGER PRIMARY KEY AUTOINCREMENT,
10+
NAME TEXT NOT NULL,
11+
CREATED_AT DATETIME default current_timestamp,
12+
COMPLETED_AT DATATIME
13+
)
14+
"""
15+
cur = db.cursor()
16+
cur.execute(query)
17+
db.close()
18+
19+
20+
create_table()
21+
22+
23+
def insert_book(name, completed_at):
24+
db = sqlite3.connect('database.db')
25+
query = """
26+
INSERT INTO BOOKS(NAME, COMPLETED_AT)
27+
28+
VALUES (?,?)
29+
"""
30+
31+
cur = db.cursor()
32+
cur.execute(query, (name, completed_at))
33+
db.commit()
34+
db.close()
35+
print('completed')
36+
37+
38+
def get_all_books():
39+
db = sqlite3.connect('database.db')
40+
statement = 'SELECT id, name, completed_at FROM BOOKS'
41+
cur = db.cursor()
42+
items_io = cur.execute(statement)
43+
item_lst = [i for i in items_io]
44+
return item_lst
45+
46+
47+
# insert_book('Time, fast or slow', datetime.datetime.now())
48+
49+
def add_book(self):
50+
title = self.title_input.text()
51+
if title:
52+
cursor.execute("INSERT INTO books (title) VALUES (?)", (title,))
53+
conn.commit()
54+
self.title_input.clear()
55+
self.load_books()
56+
57+
58+
def delete_book(book_id):
59+
# Connect to the SQLite database
60+
db = sqlite3.connect('database.db')
61+
62+
# Define the SQL query to delete a book with a specific ID
63+
query = "DELETE FROM books WHERE id = ?"
64+
65+
# Execute the query with the provided book ID as a parameter
66+
db.execute(query, (book_id,))
67+
68+
# Commit the changes to the database
69+
db.commit()
70+
71+
# Close the database connection
72+
db.close()
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
from PyQt5.QtWidgets import (QApplication, QMainWindow, QVBoxLayout, QScrollArea,
2+
QLineEdit, QFormLayout, QHBoxLayout, QFrame, QDateEdit,
3+
QPushButton, QLabel, QListWidget, QDialog, QAction, QToolBar)
4+
from PyQt5.QtCore import Qt
5+
6+
from datetime import datetime
7+
from db import (get_all_books, create_table, insert_book, delete_book)
8+
9+
10+
class CreateRecord(QFrame):
11+
def __init__(self, main_window):
12+
super().__init__()
13+
self.main_window = main_window # Pass a reference to the main window
14+
15+
self.date_entry = QDateEdit()
16+
self.book_name = QLineEdit()
17+
self.book_name.setPlaceholderText('Book name')
18+
self.add_button = QPushButton(text="Add Book")
19+
# Connect the button to add_book function
20+
self.add_button.clicked.connect(self.add_book)
21+
22+
layout = QVBoxLayout(self)
23+
layout.addWidget(QLabel('Book Name:'))
24+
layout.addWidget(self.book_name)
25+
layout.addWidget(QLabel('Completed Date:'))
26+
layout.addWidget(self.date_entry)
27+
layout.addWidget(self.add_button)
28+
29+
def add_book(self):
30+
book_name = self.book_name.text()
31+
completed_date = self.date_entry.date().toString("yyyy-MM-dd")
32+
33+
if book_name:
34+
insert_book(book_name, completed_date)
35+
# Reload the book collection after adding a book
36+
self.main_window.load_collection()
37+
self.book_name.clear() # Clear the input field
38+
39+
40+
class BookCard(QFrame):
41+
def __init__(self, book_id, bookname, completed_date):
42+
super().__init__()
43+
self.setStyleSheet(
44+
'background:white; border-radius:4px; color:black;'
45+
)
46+
self.setFixedHeight(110)
47+
self.book_id = book_id
48+
layout = QVBoxLayout()
49+
label = QLabel(f'<strong>{bookname}</strong>')
50+
51+
# Update the format string here
52+
parsed_datetime = datetime.strptime(completed_date, "%Y-%m-%d")
53+
formatted_datetime = parsed_datetime.strftime("%Y-%m-%d")
54+
55+
date_completed = QLabel(f"Completed {formatted_datetime}")
56+
delete_button = QPushButton(
57+
text='Delete', clicked=self.delete_book_click)
58+
# delete_button.setFixedWidth(60)
59+
delete_button.setStyleSheet('background:red; padding:4px;')
60+
61+
layout.addWidget(label)
62+
layout.addWidget(date_completed)
63+
layout.addWidget(delete_button)
64+
layout.addStretch()
65+
self.setLayout(layout)
66+
67+
def delete_book_click(self):
68+
delete_book(self.book_id)
69+
self.close()
70+
71+
72+
class Main(QMainWindow):
73+
def __init__(self):
74+
super().__init__()
75+
self.initUI()
76+
self.load_collection()
77+
78+
def initUI(self):
79+
self.main_frame = QFrame()
80+
self.main_layout = QVBoxLayout(self.main_frame)
81+
82+
# add register widget
83+
# Pass a reference to the main window
84+
self.register_widget = CreateRecord(self)
85+
self.main_layout.addWidget(self.register_widget)
86+
87+
books_label = QLabel('Completed Books')
88+
books_label.setStyleSheet('font-size:18px;')
89+
self.main_layout.addWidget(books_label)
90+
self.book_collection_area()
91+
92+
self.setCentralWidget(self.main_frame)
93+
94+
def book_collection_area(self):
95+
scroll_frame = QFrame()
96+
self.book_collection_layout = QVBoxLayout(scroll_frame)
97+
98+
scroll = QScrollArea()
99+
scroll.setWidgetResizable(True)
100+
scroll.setWidget(scroll_frame)
101+
scroll.setStyleSheet('QScrollArea{border:0px}')
102+
103+
self.book_collection_layout.addStretch()
104+
self.main_layout.addWidget(scroll)
105+
106+
def load_collection(self):
107+
# Clear existing book cards before reloading
108+
for i in reversed(range(self.book_collection_layout.count())):
109+
widget = self.book_collection_layout.itemAt(i).widget()
110+
if widget is not None:
111+
widget.deleteLater()
112+
113+
collections = get_all_books()
114+
for collection in collections:
115+
frame = BookCard(*collection)
116+
self.book_collection_layout.insertWidget(0, frame)
117+
118+
119+
def main():
120+
app = QApplication([])
121+
app.setStyle('fusion')
122+
win = Main()
123+
win.show()
124+
app.exec_()
125+
126+
127+
if __name__ == '__main__':
128+
main()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pyqt5

0 commit comments

Comments
 (0)