Eel is a little Python library for making simple Electron-like offline HTML/JS GUI apps, with full access to Python capabilities and libraries.
https://github.com/ChrisKnott/Eel
Install
pip install eel
C:\python_dev\crud>pip install eel
Install PyAutoGUI
https://pypi.org/project/PyAutoGUI/
pip install PyAutoGUI
C:\python_dev\crud>pip install PyAutoGUI
Create Database sqlite3 using python
createdb.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | / / createdb.py import sqlite3 from sqlite3 import Error def create_connection(db_file): """ create a database connection to a SQLite database """ conn = None try : conn = sqlite3.connect(db_file) print (sqlite3.version) except Error as e: print (e) finally : if conn: conn.close() if __name__ = = '__main__' : create_connection(r "C:\python_dev\crud\views\database\storage.db" ) |
C:\python_dev\crud>python createdb.py
Create Database Table
CREATE TABLE tblemployee (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR (150),
position VARCHAR (150),
office VARCHAR (150)
);
main.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #main.py import eel from views.models.employee import showallrecords, save_newemployee, show_selectedEmployee, update_newemployee, show_deleteEmployee eel.init( 'views' ) @eel .expose def fetchalldata(): select_reg = showallrecords() eel.action_out(select_reg) @eel .expose def btn_save(name, position, office): msg = save_newemployee(name, position, office) eel.save_return( str (msg)) @eel .expose def get_employee( id ): select_employee = show_selectedEmployee( id ) eel.action_edit(select_employee) @eel .expose def btn_update(name, position, office, id ): msg = update_newemployee(name, position, office, id ) eel.update_return( str (msg)) @eel .expose def get_delete_employee( id ): select_del_employee = show_deleteEmployee( id ) eel.delete_return(select_del_employee) eel.start( 'templates/index.html' , size = pyautogui.size() ) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | #employee.py import sqlite3 def showallrecords(): try : connect = sqlite3.connect( "views/database/storage.db" ) cursor = connect.cursor() cursor.execute( "SELECT * FROM tblemployee" ) registers = [] for item in cursor.fetchall(): #test = item[1] #print(test) registers.append(item) return registers except Exception as error: print (error) msg = "Error" return msg def save_newemployee(name, position, office): try : connect = sqlite3.connect( "views/database/storage.db" ) cursor = connect.cursor() if name ! = " " and position != " " and office != " ": cursor.execute( "INSERT INTO tblemployee(name, position, office) VALUES(?,?,?)" ,(name, position, office)) connect.commit() connect.close() msg = "success" return msg else : msg = "failure" return msg except Exception as Error: print (Error) msg = "failure" return msg def show_selectedEmployee( id ): try : connect = sqlite3.connect( "views/database/storage.db" ) cursor = connect.cursor() cursor.execute( "SELECT * FROM tblemployee WHERE id =?" , ( id ,)) editemployees = [] for item in cursor.fetchone(): editemployees.append(item) return editemployees except Exception as error: print (error) msg = "Error" return msg def update_newemployee(name, position, office, id ): try : connect = sqlite3.connect( "views/database/storage.db" ) cursor = connect.cursor() if name ! = " " and position != " " and office != " ": cursor.execute( "UPDATE tblemployee SET name =?, position =?, office =? WHERE id =?" , (name, position, office, id ,)) connect.commit() connect.close() msg = "success" return msg else : msg = "failure" return msg except Exception as Error: print (Error) msg = "failure" return msg def show_deleteEmployee( id ): try : connect = sqlite3.connect( "views/database/storage.db" ) cursor = connect.cursor() cursor.execute( "DELETE FROM tblemployee WHERE id =?" , ( id ,)) connect.commit() connect.close() msg = "success" return msg except Exception as error: print (error) msg = "Error" return msg |
crud\views\templates\index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | / / crud\views\templates\index.html <!DOCTYPE html> <html lang = "pt-br" > <head> <meta charset = "UTF-8" > <meta name = "viewport" content = "width=device-width, initial-scale=1.0" > <script type = "text/javascript" src = "/eel.js" >< / script> <link rel = "stylesheet" href = "../css/index.css" > <link rel = "icon" href = "../img/myglogo.png" > <title>Python Desktop App CRUD (Create Read Update and Delete ) sqlite3 using python eel< / title> < / head> <body> <div class = "container" > <p style = "text-align:center;" ><h2>Python Desktop App CRUD (Create Read Update and Delete ) sqlite3 using python eel< / h2>< / p> <p style = "text-align:right;" ><button type = "button" class = "btn" id = "btn_addnew" >Add New< / button>< / p> <table id = "employeedatatable" class = "styled-table" > <tr> <th> ID < / th> <th>Name< / th> <th>Position< / th> <th>Office< / th> <th>Action< / th> < / tr> < / table> <div class = "modalContainer" id = "Addnewmodal" > <div class = "modal-content" > <span id = "close" class = "close" >×< / span> <p style = "text-align:center;" ><h2>Add New Employee< / h2>< / p> <form class = "form-detail" action = "#" method = "post" id = "myform" > <div class = "form-row" > <label>Full Name:< / label> < input type = "text" name = "txtfullname" id = "txtfullname" class = "input-text" required placeholder = "ex: Cairocoders Ednalan" > < / div> <div class = "form-row" > <label>Position:< / label> < input type = "text" name = "txtposition" id = "txtposition" class = "input-text" required> < / div> <div class = "form-row" > <label>Office:< / label> < input type = "text" name = "txtoffice" id = "txtoffice" class = "input-text" required> < / div> <div class = "form-row-last" > < input type = "submit" name = "register" class = "button" value = "Add New Employee" onclick = "save_register_js();" > < / div> <div class = "box" ><label class = "label_input" id = "return_register" style = "width: 90%;color:green;font-weight:bold;" >< / label>< / div> < / form> < / div> < / div> <div class = "modalContainer" id = "Edit_modal" > <div class = "modal-content" > <span id = "close" class = "closeedit" >×< / span> <p style = "text-align:center;" ><h2>Edit Employee< / h2>< / p> <form class = "form-detail" action = "#" method = "post" id = "myformedit" >< input type = "hidden" name = "id" id = "id" > <div class = "form-row" > <label>Full Name:< / label> < input type = "text" name = "edit_name" id = "edit_name" class = "input-text" required> < / div> <div class = "form-row" > <label>Position:< / label> < input type = "text" name = "edit_position" id = "edit_position" class = "input-text" required> < / div> <div class = "form-row" > <label>Office:< / label> < input type = "text" name = "edit_office" id = "edit_office" class = "input-text" required> < / div> <div class = "form-row-last" > < input type = "submit" name = "register" class = "button" value = "Update" onclick = "save_edit();" > < / div> <div class = "box" ><label class = "label_input" id = "return_update" style = "width: 90%;color:green;font-weight:bold;" >< / label>< / div> < / form> < / div> < / div> <div class = "modalContainer" id = "Delete_modal" > <div class = "modal-content" > <span id = "close" class = "closedelete" >×< / span> <p style = "text-align:center;" ><h2>Delete Employee< / h2>< / p> <p style = "text-align:center;" ><h3>Are you sure you want to delete this data?< / h3>< / p> <div class = "form-detail" > < input type = "hidden" name = "idvalue" id = "idvalue" > < input type = "submit" name = "btndelete" class = "button" value = "Delete" onclick = "btn_submitdelete($('#idvalue').val());" > <div class = "box" ><label class = "label_input" id = "return_delete" style = "width: 90%;color:green;font-weight:bold;" >< / label>< / div> < / div> < / div> < / div> < / div> <script type = "text/javascript" src = "../js/jquery.min.js" >< / script> <script type = "text/javascript" src = "../js/jquery.validate.min.js" >< / script> <script type = "text/javascript" src = "../js/main.js" >< / script> < / body> < / html> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | #crud\views\js\main.js $(document).ready(function(){ eel.fetchalldata() $( "#btn_addnew" ).on( "click" , function() { $( "#Addnewmodal" ).show(); }); $( ".close" ).on( "click" , function() { $( "#Addnewmodal" ).hide(); }); $( ".closeedit" ).on( "click" , function() { $( "#Edit_modal" ).hide(); }); $( ".closedelete" ).on( "click" , function() { $( "#Delete_modal" ).hide(); }); }) function link(target) { window.location.href = target; } eel.expose(action_out) function action_out(registers){ / / alert( "Show Table" ); registers.forEach(showdata) } eel.expose(action_edit) function action_edit(editemployees){ / / alert(editemployees); editemployees.forEach(get_array_values) } function get_array_values(item, index){ / / alert(item); / / alert(index); if (index = = 0 ) { document.getElementById( "id" ).value = item; } else if (index = = 1 ) { document.getElementById( "edit_name" ).value = item; } else if (index = = 2 ) { document.getElementById( "edit_position" ).value = item; } else if (index = = 3 ) { document.getElementById( "edit_office" ).value = item; } else {} } / / SAVE async function save_edit(){ $( "#myformedit" ).validate({ messages: { edit_name: { required: "Please provide Name" }, edit_position: { required: "Please provide Position" }, edit_office: { required: "Please provide Office" }, }, submitHandler: function(form) { eel.btn_update($( '#edit_name' ).val(),$( '#edit_position' ).val(),$( '#edit_office' ).val(),$( '#id' ).val()) / / alert( "Success" ); } }); } function showdata(item, index){ var get_table = document.getElementById( "employeedatatable" ); var tr = document.createElement( "tr" ); var td = document.createElement( "td" ); var td2 = document.createElement( "td" ); var td3 = document.createElement( "td" ); var td4 = document.createElement( "td" ); var td5 = document.createElement( "td" ); var id = item[ 0 ] td.innerText = item[ 0 ] td2.innerText = item[ 1 ] td3.innerText = item[ 2 ] td4.innerText = item[ 3 ] td5.innerHTML = '<button type="button" class="btn" onclick="btn_edit(' + id + ')">Edit</button> | <button type="button" class="btndelete" onclick="buttondelete((' + id + '))">Delete</button>' get_table.appendChild(tr) tr.appendChild(td) tr.appendChild(td2) tr.appendChild(td3) tr.appendChild(td4) tr.appendChild(td5) } / / NEW Employee async function save_register_js(){ $( "#myform" ).validate({ messages: { txtfullname: { required: "Please provide Name" }, txtposition: { required: "Please provide Position" }, txtoffice: { required: "Please provide Office" }, }, submitHandler: function(form) { eel.btn_save($( '#txtfullname' ).val(),$( '#txtposition' ).val(),$( '#txtoffice' ).val()) } }); }; eel.expose(save_return); function save_return(status){ if (status = = "success" ){ $( '#return_register' ).text( 'New Employee completed successfully!' ); $( '#txtfullname' ).val(''); $( '#txtposition' ).val(''); $( '#txtoffice' ).val(''); } if (status = = "failure" ){ $( '#return_register' ).text( 'Error when registering, make sure you have no blank fields.' ); } }; eel.expose(edit_return); function edit_return(status){ if (status = = "success" ){ $( '#return_register' ).text( 'Employee Updated successfully!' ); } if (status = = "failure" ){ $( '#return_register' ).text( 'Error when updating, make sure you have no blank fields.' ); } }; function buttondelete( id ) { document.getElementById( "idvalue" ).value = id ; $( "#Delete_modal" ).show(); } async function btn_edit( id ){ eel.get_employee( id ) $( "#Edit_modal" ).show(); } async function btn_submitdelete( id ){ / / alert( id ); eel.get_delete_employee( id ) } eel.expose(update_return); function update_return(status){ if (status = = "success" ){ $( '#return_update' ).text( 'Employee Updated successfully!' ); $( '#txtfullname' ).val(''); $( '#txtposition' ).val(''); $( '#txtoffice' ).val(''); } if (status = = "failure" ){ $( '#return_update' ).text( 'Error when updating record, make sure you have no blank fields.' ); } }; eel.expose(delete_return) function delete_return(delemployees){ alert(delemployees); if (status = = "success" ){ location.href = "index.html" ; } if (status = = "failure" ){ $( '#return_delete' ).text( 'Error deleting record' ); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | //crud\views\css\index.css body { color: #162D5D; font-family: 'Roboto' , sans-serif; } .container {margin:30px;} .styled-table { border-collapse: collapse;width:100%; margin: 25px 0; font-size: 0.9em; font-family: sans-serif; min-width: 400px; box-shadow: 0 0 20px rgba(0, 0, 0, 0.15); } .styled-table thead tr { background-color: #009879; color: #ffffff; text-align: left; } .styled-table th, .styled-table td { padding: 12px 15px; } .styled-table tr { border-bottom: 1px solid #dddddd; } .styled-table tr:nth-of-type(even) { background-color: #f3f3f3; } .styled-table tr:last-of-type { border-bottom: 2px solid #009879; } .btn { background-color: #04AA6D!important; border-radius: 5px;color:#ffffff; font-size: 17px; font-family: 'Source Sans Pro' , sans-serif; padding: 6px 18px; } .btndelete { background-color: #cf2e2e!important; border-radius: 5px;color:#ffffff; font-size: 17px; font-family: 'Source Sans Pro' , sans-serif; padding: 6px 18px; } .form-detail .form-row label.error { color: red; } .form-detail .input-text { margin-bottom: 27px; } .form-detail input { width: 91%; padding: 14.5px 15px; border: 1px solid #e5e5e5; border-radius: 5px; -o-border-radius: 5px; -ms-border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; appearance: unset; -moz-appearance: unset; -webkit-appearance: unset; -o-appearance: unset; -ms-appearance: unset; outline: none; -moz-outline: none; -webkit-outline: none; -o-outline: none; -ms-outline: none; font-family: 'Roboto' , sans-serif; font-size: 16px; color: #333; } .form-detail .form-row input:focus { border: 1px solid #53c83c; } .form-detail .button { background: #3b63ca; border-radius: 6px; -o-border-radius: 6px; -ms-border-radius: 6px; -moz-border-radius: 6px; -webkit-border-radius: 6px; width: 160px; border: none; margin: 6px 0 50px 0px; cursor: pointer; font-family: 'Roboto' , sans-serif; color: #fff; font-weight: 500; font-size: 16px; } .form-detail .button:hover { background: #3356b0; } .modalContainer { display: none; position: fixed; z-index: 1; left: 0; top: 0; width: 100%; height: 100%; background-color: rgb(0, 0, 0); background-color: rgba(0, 0, 0, 0.4); } .modal-content { background-color: #fefefe; margin: 15% auto; padding: 20px; border: 1px solid #888; width: 40%; } #close { color: #aaa; float: right; font-size: 28px; font-weight: bold; cursor: pointer; } |
https://jquery.com/download/
CDN : jsDelivr CDN
https://www.jsdelivr.com/package/npm/jquery
https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js
jQuery Validation
http://jqueryvalidation.org/
Run : C:\python_dev\crud>python main.py