Membuat Aplikasi Desktop CRUD Python dan MySQL

Membuat Aplikasi Desktop CRUD Python dan MySQL
Desain program

Langkah 1 : Membuat Database

database yang akan kita gunakan untuk membuat aplikasi CRUD diatas menggunakan MySQL, buatlah sebuah database baru dengan nama bookstore dengan nama tabel books dan  kolom-kolom yang terdiri dari : 
  • id (integer,primary key,autoincrement)
  • title (varchar 255)
  • year (varchar 255)
  • author (varchar 255)
  • isbn (integer)
jika menggunakan phpmyadmin maka akan seperti pada gambar berikut:
desain table

atau jalankan script berikut :
CREATE TABLE `books` (
  `id` int(11) NOT NULL,
  `title` varchar(255) NOT NULL,
  `year` varchar(255) NOT NULL,
  `author` varchar(255) NOT NULL,
  `isbn` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Jika sudah tambahkan 10 records.

Langkah 2 : Desain Interface

pada contoh kasus kali ini untuk pembuatan desain kita akan menggunakan tools yaitu pygubu designer yang akan membantu kita agar lebih mudah untuk membuat desain. tools ini menggunakan library tkinter untuk membuat aplikasi desktop, sebagai mana kita ketahui selain tkinter masih ada beberapa libarary yang dapat kita gunakan. untuk menginstal pygubu desinger silahkan install pygubu designer dengan perintah :
pip install pygubu-designer
jika sudah tersinstal buka aplikasi pygubu designer dengan mengetik perintah
pygubu-designer
pada cmd selanjutnya kita langsung buat design nya seperti pada gambar berikut :
Membuat Aplikasi Desktop CRUD Python dan MySQL


Berikan id pada setiap komponen yang ada pada form diatas berikut adalah pemberian id yang akan digunakan pada kasus ini :
  • txt_title
  • txt_author
  • txt_year
  • txt_isbn
  • btn_view_all
  • btn_search
  • btn_add
  • btn_update
  • btn_delete
  • btn_close
  • list_book
selanjutnya kita akan memberika command pada setiap tombol, untuk memberikan command silahkan pilih tombolnya kemudian buka jendela sebelah kiri pada object properties dan geser kebawah, anda akan menemukan perintah command callback, misalkan kita akan memberikan command pada tombol View All dengan command : view_command
Membuat Aplikasi Desktop CRUD Python dan MySQL

berikut adalah detail command yang akan kita berikan pada setiap tombol :
  1. Tombol View All : view_command
  2. Tombol Search Entry : search_command
  3. Tombol Add Entry : add_command
  4. Tombol Update : update_command
  5. Tombol Delete : delete_command
  6. Tombol Close : close_command
jika sudah selesai saatnya kita menggenerate design pada pygubu designer kedalam bentuk coding python dengan cara click menu code kemudian pilih tab code script dan tekan tombol Generatesetelah itu tekan tombol Copy to Clipboard.
Membuat Aplikasi Desktop CRUD Python dan MySQL

Hasil Generate dari pygubu designer akan menjadi seperti berikut :
import pathlib
import pygubu
import tkinter as tk
import tkinter.ttk as ttk

PROJECT_PATH = pathlib.Path(__file__).parent
PROJECT_UI = PROJECT_PATH / "bookstore.ui"


class BookstoreApp:
    def __init__(self, master=None):
        # build ui
        self.toplevel1 = tk.Tk() if master is None else tk.Toplevel(master)
        self.frame1 = tk.Frame(self.toplevel1)
        self.txt_title = tk.Entry(self.frame1)
        self.txt_title.grid(column='1', row='0')
        self.txt_author = tk.Entry(self.frame1)
        self.txt_author.grid(column='3', row='0')
        self.txt_year = tk.Entry(self.frame1)
        self.txt_year.grid(column='1', row='1')
        self.txt_isbn = tk.Entry(self.frame1)
        self.txt_isbn.grid(column='3', row='1')
        self.label2 = tk.Label(self.frame1)
        self.label2.configure(text='Author :')
        self.label2.grid(column='2', row='0')
        self.label3 = tk.Label(self.frame1)
        self.label3.configure(text='Year :')
        self.label3.grid(column='0', row='1')
        self.label4 = tk.Label(self.frame1)
        self.label4.configure(text='ISBN :')
        self.label4.grid(column='2', row='1')
        self.label5 = tk.Label(self.frame1)
        self.label5.configure(text='Title :')
        self.label5.grid(column='0', row='0')
        self.list_book = tk.Listbox(self.frame1)
        self.list_book.configure(activestyle='dotbox', width='45')
        self.list_book.grid(column='0', columnspan='3', pady='5', row='2', rowspan='6')
        self.btn_view_all = tk.Button(self.frame1)
        self.btn_view_all.configure(text='View All', width='15')
        self.btn_view_all.grid(column='3', row='2')
        self.btn_view_all.configure(command=self.view_command)
        self.btn_search = tk.Button(self.frame1)
        self.btn_search.configure(text='Search Entry', width='15')
        self.btn_search.grid(column='3', row='3')
        self.btn_search.configure(command=self.search_command)
        self.btn_add = tk.Button(self.frame1)
        self.btn_add.configure(text='Add Entry', width='15')
        self.btn_add.grid(column='3', row='4')
        self.btn_add.configure(command=self.add_command)
        self.btn_update = tk.Button(self.frame1)
        self.btn_update.configure(text='Update', width='15')
        self.btn_update.grid(column='3', row='5')
        self.btn_update.configure(command=self.update_command)
        self.btn_delete = tk.Button(self.frame1)
        self.btn_delete.configure(text='Delete', width='15')
        self.btn_delete.grid(column='3', row='6')
        self.btn_delete.configure(command=self.delete_command)
        self.btn_close = tk.Button(self.frame1)
        self.btn_close.configure(text='Close', width='15')
        self.btn_close.grid(column='3', row='7')
        self.btn_close.configure(command=self.close_command)
        self.frame1.configure(height='200', padx='20', pady='20', width='200')
        self.frame1.grid(column='0', row='0')
        self.toplevel1.configure(height='200', width='200')
        self.toplevel1.resizable(False, False)
        self.toplevel1.title('Bookstore')

        # Main widget
        self.mainwindow = self.toplevel1
    
    def run(self):
        self.mainwindow.mainloop()

    def view_command(self):
        pass

    def search_command(self):
        pass

    def add_command(self):
        pass

    def update_command(self):
        pass

    def delete_command(self):
        pass

    def close_command(self):
        pass


if __name__ == '__main__':
    app = BookstoreApp()
    app.run()

Jika belum paham bagaimana cara membuat design menggunakan pygubu-designer anda dapat mengunjungi github pembuatnya pada url berikut: https://github.com/alejandroautalan/pygubu-designer

Langkah 3 : Bekerja dengan Visual Studio Code

Setelah anda menyelesaikan desain saatnya kita bekerja dengan visual studio code atau vscode. buatlah sebuah folder baru pada komputer anda dan buka folder tersebut dengan vscode. jika sudah tambahkan sebuah file baru dengan nama bookForm.py pastekan coding yang sudah kita copy pada pygubu designer kepada file tersebut :
Membuat Aplikasi Desktop CRUD Python dan MySQL


Tambahkan sebuah file lagi untuk mengelola perintah CRUD dengan nama book.py kemudian masukan coding berikut :
import sqlite3
import mysql.connector

def connect():
    conn = mysql.connector.connect(
    host="localhost",
    user="root",
    passwd="",
    database="bookstore"
    )

    if conn.is_connected():
        print("Berhasil terhubung ke database")
    return conn

def insert(title, author, year, isbn):
    conn=connect()
    cur = conn.cursor()
    sql = "INSERT INTO books (title, year, author, isbn) VALUES (%s,%s,%s,%s)"
    val = (title, year,author,isbn)
    cur.execute(sql,val)
    conn.commit()
    conn.close()

def view():
    conn=connect()
    cur = conn.cursor()
    cur.execute("SELECT * FROM books")
    rows = cur.fetchall()
    conn.close()
    return rows

def search(title="", author="", year="", isbn=""):          # pass empty strings as default values
    conn = connect()
    cur = conn.cursor()
    sql = "select * from books where title=%s or year=%s or author=%s or isbn=%s"
    val = (title, year,author,isbn)
    cur.execute(sql,val)
    rows = cur.fetchall()
    conn.close()
    return rows

def delete(id):
    conn = connect()
    cur = conn.cursor()
    sql="DELETE FROM books WHERE id=%s"
    val=(id)
    cur.execute(sql,val)
    conn.commit()
    conn.close()

def update(id, title, author, year, isbn):
    conn = connect()
    cur = conn.cursor()
    sql="UPDATE books SET title=%s, author=%s, year=%s, isbn=%s WHERE id=%s"
    val=(id, title, author, year, isbn)
    cur.execute(sql,val)
    conn.commit()
    conn.close()

connect()

Langkah 4 : Memasukan Perintah

setelah kita membuat perintah untuk operasi tampil data,ubah data,update dan hapus selanjutnya kita akan memanggilnya pada setiap tombol yang ada pada design yang telah kita buat, modifikasi setiap fungsi yang ada pada design, update Coding yang ada pada bookForm.py menjadi seperti berikut :
import pathlib
import pygubu
import tkinter as tk
import tkinter.ttk as ttk
from tkinter import messagebox
import book
PROJECT_PATH = pathlib.Path(__file__).parent
PROJECT_UI = PROJECT_PATH / "bookstore.ui"


class BookstoreApp:
    def __init__(self, master=None):
        # build ui
        self.toplevel1 = tk.Tk() if master is None else tk.Toplevel(master)
        self.frame1 = tk.Frame(self.toplevel1)
        self.txt_title = tk.Entry(self.frame1)
        self.txt_title.grid(column='1', row='0')
        self.txt_author = tk.Entry(self.frame1)
        self.txt_author.grid(column='3', row='0')
        self.txt_year = tk.Entry(self.frame1)
        self.txt_year.grid(column='1', row='1')
        self.txt_isbn = tk.Entry(self.frame1)
        self.txt_isbn.grid(column='3', row='1')
        self.label2 = tk.Label(self.frame1)
        self.label2.configure(text='Author :')
        self.label2.grid(column='2', row='0')
        self.label3 = tk.Label(self.frame1)
        self.label3.configure(text='Year :')
        self.label3.grid(column='0', row='1')
        self.label4 = tk.Label(self.frame1)
        self.label4.configure(text='ISBN :')
        self.label4.grid(column='2', row='1')
        self.label5 = tk.Label(self.frame1)
        self.label5.configure(text='Title :')
        self.label5.grid(column='0', row='0')
        self.list_book = tk.Listbox(self.frame1)
        self.list_book.configure(width='45')
        self.list_book.grid(column='0', columnspan='3', pady='5', row='2', rowspan='6')
        self.list_book.bind('<<ListboxSelect>>',self.get_selected_row)
        self.btn_view_all = tk.Button(self.frame1)
        self.btn_view_all.configure(text='View All', width='15')
        self.btn_view_all.grid(column='3', row='2')
        self.btn_view_all.configure(command=self.view_command)
        self.btn_search = tk.Button(self.frame1)
        self.btn_search.configure(text='Search Entry', width='15')
        self.btn_search.grid(column='3', row='3')
        self.btn_search.configure(command=self.search_command)
        self.btn_add = tk.Button(self.frame1)
        self.btn_add.configure(text='Add Entry', width='15')
        self.btn_add.grid(column='3', row='4')
        self.btn_add.configure(command=self.add_command)
        self.btn_update = tk.Button(self.frame1)
        self.btn_update.configure(text='Update', width='15')
        self.btn_update.grid(column='3', row='5')
        self.btn_update.configure(command=self.update_command)
        self.btn_delete = tk.Button(self.frame1)
        self.btn_delete.configure(text='Delete', width='15')
        self.btn_delete.grid(column='3', row='6')
        self.btn_delete.configure(command=self.delete_command)
        self.btn_close = tk.Button(self.frame1)
        self.btn_close.configure(text='Close', width='15')
        self.btn_close.grid(column='3', row='7')
        self.btn_close.configure(command=self.close_command)
        self.frame1.configure(height='200', padx='20', pady='20', width='200')
        self.frame1.pack(side='top')
        self.toplevel1.configure(height='200', width='200')
        self.toplevel1.title('Bookstore')
        self.view_command()
        # Main widget
        self.mainwindow = self.toplevel1
    
    def run(self):
        self.mainwindow.mainloop()

    def get_selected_row(self,event):
        try:
            global selected_tuple
            for i  in self.list_book.curselection():
                selected_tuple=self.list_book.get(i)[0]
            # Show the selected data in the Entry area
            print(self.list_book.get(i)[0])
            self.txt_title.delete(0,tk.END)
            self.txt_title.insert(tk.END,self.list_book.get(i)[1])
            self.txt_author.delete(0,tk.END)
            self.txt_author.insert(tk.END,self.list_book.get(i)[3])
            self.txt_year.delete(0,tk.END)
            self.txt_year.insert(tk.END,self.list_book.get(i)[2])
            self.txt_isbn.delete(0,tk.END)
            self.txt_isbn.insert(tk.END,self.list_book.get(i)[4])
        except IndexError:                         # When the listbox is empty, try to access lst1.curselection()[0] will throw an error.
            pass
        
    def view_command(self):
        self.list_book.delete(0,tk.END)  
        for row in book.view():
            self.list_book.insert(tk.END,row)
    def search_command(self):
        self.list_book.delete(0,tk.END)
        for row in book.search(self.txt_title.get(), self.txt_author.get(), self.txt_year.get(), self.txt_isbn.get()):
            self.list_book.insert(tk.END,row)

    def add_command(self):
        book.insert(self.txt_title.get(), self.txt_author.get(), self.txt_year.get(), self.txt_isbn.get())
        self.list_book.delete(0,tk.END)
       
     
        self.view_command()
        
    def update_command(self):
        book.update(selected_tuple, self.txt_title.get(), self.txt_author.get(), self.txt_year.get(), self.txt_isbn.get())
        self.view_command()

    def delete_command(self):
        book.delete(selected_tuple)
        messagebox.showinfo(title="Info", message="Berhasil Dihapus.")
        self.view_command()

    def close_command(self):
        self.toplevel1.destroy()


if __name__ == '__main__':
    app = BookstoreApp()
    app.run()

Langkah 5 : Menjalankan Program

untuk menjalankan program buka terminal pada vscode jika tidak muncul tekan tombol ctrl+j  kemudian ketik perintah berikut : 
python3 bookform.py
Silahkan ujicoba program anda untuk menginput data,ubah data dan hapus data.  untuk mengubah data atau menghapus data pilih dulu data yang akan kita eksekusi dengan cara klik data nya pada list_book. kemudian tekan tombolnya.

Langkah 6 : Membuat File .exe

berikut akan dijelaskan cara membuat file .exe pada project yang kita buat, pertama anda perlu melakukan install sebuah library baru namanya adalah pyinstaller, jalankan perintah berikut pada cmd anda :
>pip install pyinstaller
  
how to install pyinstaller

Tunggu proses instalasi sampai selesai, kemudian buka folder project anda menggunakan visual studio code. kemudian jalankan perintah berikut pada terminal :
pyinstaller --noconsole --onefile bookForm.py

how to create exe in python desktop

tunggu proses berjalan sampai dengan selesai, jika proses sudah berhenti maka akan bertambah beberapa folder pada project anda, file .exe yang sudah berhasil dibuat berada pada folder dist/bookForm.exe. silahkan buka file tersebut jika muncul berarti anda sudah berhasil membuat file .exe dari project yang kita buat. 
how to create exe file in python

Selanjutnya untuk membuka aplikasi yang kita buat tidak perlu lagi menjankan script ataupun membukanya pada Visual Studio Code. Sekian Membuat Aplikasi Desktop CRUD Python dan MySQL dengan library tkinter dan pygubu designer semoga bermanfaat.