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\login_register>pip install eel
Create Database sqlite3 using python
#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\login_register\views\database\storage.db")run
C:\python_dev\registration>createdb.py
Install PyAutoGUI
PyAutoGUI is a cross-platform GUI automation Python module for human beings. Used to programmatically control the mouse & keyboard.
pip install PyAutoGUI
C:\python_dev\registration>pip install PyAutoGUI
Install werkzeug
pip install werkzeug
C:\python_dev\registration>pip install werkzeug
from werkzeug.security import generate_password_hash, check_password_hash #pip install werkzeug
main.py
#main.py from __future__ import print_function import eel from views.models.signup import save_register from views.models.login import login_user, login_session import pyautogui #https://pypi.org/project/PyAutoGUI/ eel.init('views') @eel.expose def btn_login(user_name, password): msg = login_user(user_name, password) eel.login_return(str(msg)) @eel.expose def get_user_online(): get_user = login_session() print(get_user) eel.get_user(str(get_user)) @eel.expose def btn_save(name, email, passw): msg = save_register(name, email, passw) eel.save_return(str(msg)) eel.start( 'index.html', size=pyautogui.size() )Create Table
CREATE TABLE tblusers (
id INTEGER PRIMARY KEY AUTOINCREMENT
UNIQUE,
name VARCHAR (150),
email VARCHAR (150),
password VARCHAR (150)
);
CREATE TABLE user_session (
id INTEGER PRIMARY KEY AUTOINCREMENT
UNIQUE,
user VARCHAR (150)
);
login_registration/views/models/signup.py
#registration/views/models/signup.py import sqlite3 from werkzeug.security import generate_password_hash #pip install werkzeug def save_register(name, email, passw): try: connect = sqlite3.connect("views/database/storage.db") cursor = connect.cursor() _hashed_password = generate_password_hash(passw) print(_hashed_password) cursor.execute("INSERT OR REPLACE INTO user_session(id) VALUES(?)", (1,)) if name != "" and passw != "" and email != "": cursor.execute("INSERT INTO tblusers(name, email, password) VALUES(?,?,?)",(name, email, _hashed_password)) connect.commit() connect.close() msg = "success" return msg else: msg = "failure" return msg except Exception as Error: print(Error) msg = "failure" return msglogin_registration/views/models/login.py
#registration/views/models/login.py import sqlite3 from werkzeug.security import generate_password_hash, check_password_hash #pip install werkzeug def login_user(user_name, password): #print(user_name) #print(password) try: connect = sqlite3.connect("views/database/storage.db") cursor = connect.cursor() cursor.execute("SELECT * FROM tblusers WHERE email =?", (user_name,)) get_password = cursor.fetchone() password_rs = get_password[3] if check_password_hash(password_rs, password): cursor.execute("SELECT * FROM tblusers WHERE email =?", (user_name,)) user = cursor.fetchone() cursor.execute("UPDATE user_session SET user =? WHERE id =?", (user[1], 1,)) connect.commit() msg = "success" connect.close() return msg else: msg = "failed" connect.close() return msg except Exception as Error: print(Error) msg = "failed" return msg def login_session(): try: connect = sqlite3.connect("views/database/storage.db") cursor = connect.cursor() cursor.execute("SELECT user FROM user_session WHERE id =?", (1,)) get_user_online = cursor.fetchone() user_online = [] for name in get_user_online: user_online.append(name) connect.close() return user_online[0] except Exception as error: user_online = "error" print(error) return user_onlineMake your Front-end HTML CSS and Javascript
login_registration/views/index.html
//login_registration/views/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/password.png"> <title>Python Login Registration</title> </head> <body class="form-v2"> <div class="page-content"> <div class="form-v2-content" id="login-form"> <div class="form-left"> <img src="img/form-v1.jpg" alt="form"> </div> <form class="form-detail" action="#" method="post" id="myformlogin"> <h2>Member Login</h2> <div class="form-row"> <label for="your_email">Your Email:</label> <input type="text" name="loginmail" id="loginmail" class="input-text" required pattern="[^@]+@[^@]+.[a-zA-Z]{2,6}"> </div> <div class="form-row"> <label for="password">Password:</label> <input type="password" name="loginpassword" id="loginpassword" class="input-text" required> </div> <div class="form-row-last"> <input type="submit" name="login" class="login" value="Login" onclick="btnlogin();"> <p>Don't have an account? <a href="#" id="register-form-link">Register</a></p> </div> <div class="box"><label class="label_input" id="return_login" style="width: 90%;color:red;font-weight:bold;"></label></div> </form> </div> <div class="form-v2-content" id="register-form"> <div class="form-left"> <img src="img/form-v2.jpg" alt="form"> </div> <form class="form-detail" action="#" method="post" id="myform"> <h2>Registration Form</h2> <div class="form-row"> <label for="full-name">Full Name:</label> <input type="text" name="txtfullname" id="txtfullname" class="input-text" required placeholder="ex: Cairocoders Ednalan"> </div> <div class="form-row"> <label for="your_email">Your Email:</label> <input type="text" name="txtemail" id="txtemail" class="input-text" required pattern="[^@]+@[^@]+.[a-zA-Z]{2,6}"> </div> <div class="form-row"> <label for="password">Password:</label> <input type="password" name="password" id="password" class="input-text" required> </div> <div class="form-row"> <label for="comfirm-password">Confirm Password:</label> <input type="password" name="confirm_password" id="confirm_password" class="input-text" required> </div> <div class="form-row-last"> <input type="submit" name="register" class="register" value="Register" onclick="save_register_js();"> <p>Already Registered? <a href="#" class="active" id="login-form-link">Login</a></p> </div> <div class="box"><label class="label_input" id="return_register" style="width: 90%;color:green;font-weight:bold;"></label></div> </form> </div> </div> <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script> <script src="https://cdn.jsdelivr.net/jquery.validation/1.16.0/jquery.validate.min.js"></script> <script> jQuery.validator.setDefaults({ debug: true, success: function(label){ label.attr('id', 'valid'); }, }); // NEW USER REGISTRATION async function save_register_js(){ $( "#myform" ).validate({ rules: { password: "required", confirm_password: { equalTo: "#password" } }, messages: { txtfullname: { required: "Please provide Name" }, txtemail: { required: "Please provide Email" }, password: { required: "Please provide Password" }, confirm_password: { required: "Please provide Password", equalTo: "Wrong Password" } }, submitHandler: function(form) { eel.btn_save($('#txtfullname').val(),$('#txtemail').val(),$('#password').val()) } }); }; eel.expose(save_return); function save_return(status){ if (status == "success"){ $('#return_register').text('Registration completed successfully!'); $('#txtfullname').val(''); $('#txtemail').val(''); $('#password').val(''); } if (status == "failure"){ $('#return_register').text('Error when registering, make sure you have no blank fields.'); } }; // USER LOGIN async function btnlogin(){ $( "#myformlogin" ).validate({ rules: { loginpassword: "required" }, messages: { loginmail: { required: "Please provide Email" }, loginpassword: { required: "Please provide Password" } }, submitHandler: function(form) { eel.btn_login($('#loginmail').val(), $('#loginpassword').val()) } }); }; eel.expose(login_return) function login_return(status){ //alert(status); if (status == "success"){ location.href = "admin.html"; } if (status == "failed"){ $('#return_login').text("Incorrect User or Password") } } $(function() { $("#register-form").hide(); $('#login-form-link').click(function(e) { $("#login-form").delay(100).fadeIn(100); $("#register-form").fadeOut(100); $("#register-form").hide(); $("#login-form").show(); e.preventDefault(); }); $('#register-form-link').click(function(e) { $("#register-form").delay(100).fadeIn(100); $("#login-form").fadeOut(100); $("#register-form").show(); $("#login-form").hide(); e.preventDefault(); }); }); </script> </body> </html>login_registration/views/admin.html
//login_registration/views/admin.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="icon" href="img/password.png"> <title>Admin</title> </head> <body> <div class="container"> <h1 id="user_logged_id"></h1> </div> <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script> <script type="text/javascript"> $(document).ready(function(){ eel.get_user_online() }) eel.expose(get_user) function get_user(user){ $('#user_logged_id').text('User logged in: '+ user) } </script> </body> </html>login_registration/views/css/index.css
//login_registration/views/css/index.css body { margin: 0; } .page-content { width: 100%; margin: 0 auto; background: -webkit-linear-gradient(left, #3931af, #00c6ff); display: flex; display: -webkit-flex; justify-content: center; -o-justify-content: center; -ms-justify-content: center; -moz-justify-content: center; -webkit-justify-content: center; align-items: center; -o-align-items: center; -ms-align-items: center; -moz-align-items: center; -webkit-align-items: center; } .form-v2-content { background: #fff; width: 851px; border-radius: 15px; -o-border-radius: 15px; -ms-border-radius: 15px; -moz-border-radius: 15px; -webkit-border-radius: 15px; margin: 100px 0; position: relative; display: flex; display: -webkit-flex; } .form-v2-content .form-left { margin-bottom: -4px; position: relative; } .form-v2-content .form-left img { border-top-left-radius: 15px; border-bottom-left-radius: 15px; } .form-v2-content .form-left .text-1, .form-v2-content .form-left .text-2 { font-family: 'Roboto', sans-serif; font-weight: 700; color: #fff; } .form-v2-content .form-left .text-1 { position: absolute; left: 9%; bottom: 15%; } .form-v2-content .form-left .text-2 { position: absolute; right: 8%; bottom: 1.5%; } .form-v2-content .form-left .text-1 p { font-size: 32px; line-height: 1.67; } .form-v2-content .form-detail { padding: 20px 40px 20px 40px; position: relative; width: 100%; } .form-v2-content .form-detail h2 { font-family: 'Roboto', sans-serif; font-weight: 700; color: #333; font-size: 28px; position: relative; padding: 6px 0 0; margin-bottom: 25px; } .form-v2-content .form-row { width: 100%; position: relative; } .form-v2-content .form-detail label { font-family: 'Roboto', sans-serif; font-weight: 400; font-size: 16px; color: #666; display: block; margin-bottom: 11px; } .form-v2-content .form-detail .form-row label#valid { position: absolute; right: 20px; top: 50%; transform: translateY(-50%); -o-transform: translateY(-50%); -moz-transform: translateY(-50%); -ms-transform: translateY(-50%); -webkit-transform: translateY(-50%); width: 14px; height: 14px; border-radius: 50%; -o-border-radius: 50%; -ms-border-radius: 50%; -moz-border-radius: 50%; -webkit-border-radius: 50%; background: #53c83c; } .form-v2-content .form-detail .form-row label#valid::after { content: ""; position: absolute; left: 5px; top: 1px; width: 3px; height: 8px; border: 1px solid #fff; border-width: 0 2px 2px 0; -webkit-transform: rotate(45deg); -ms-transform: rotate(45deg); -o-transform: rotate(45deg); -moz-transform: rotate(45deg); transform: rotate(45deg); } .form-v2-content .form-detail .form-row label.error { padding-left: 0; margin-left: 0; display: block; position: absolute; bottom: -10px; width: 100%; background: none; color: red; } .form-v2-content .form-detail .input-text { margin-bottom: 27px; } .form-v2-content .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-v2-content .form-detail .form-row input:focus { border: 1px solid #53c83c; } .form-v2-content .form-detail input[type="radio"] { outline: none; -moz-outline: none; -webkit-outline: none; -o-outline: none; -ms-outline: none; -o-appearance: none; -ms-appearance: none; -webkit-appearance: none; -moz-appearance: none; appearance: none; display: inline-block; width: 20px; height: 20px; padding: 4px; background-clip: content-box; border: 1px solid #e5e5e5; background-color: #fff; border-radius: 50%; -o-border-radius: 50%; -ms-border-radius: 50%; -moz-border-radius: 50%; -webkit-border-radius: 50%; cursor: pointer; float: left; margin-top: 0; } .form-v2-content .form-detail .register { 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-v2-content .form-detail .login { background: #ee6c4d; 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-v2-content .form-detail .register:hover { background: #3356b0; } .form-v2-content .form-detail .form-row-last input { padding: 15.5px; } input::-webkit-input-placeholder { /* Chrome/Opera/Safari */ color: #999; font-size: 14px; } input::-moz-placeholder { /* Firefox 19+ */ color: #999; font-size: 14px; } input:-ms-input-placeholder { /* IE 10+ */ color: #999; font-size: 14px; } input:-moz-placeholder { /* Firefox 18- */ color: #999; font-size: 14px; } /* Responsive */ @media screen and (max-width: 991px) { .form-v2-content { margin: 180px 20px; flex-direction: column; -o-flex-direction: column; -ms-flex-direction: column; -moz-flex-direction: column; -webkit-flex-direction: column; } .form-v2-content .form-left { width: 100%; } .form-v2-content .form-left img { width: 100%; border-bottom-left-radius: 0px; border-top-right-radius: 15px; } .form-v2-content .form-detail { padding: 30px 20px 30px 20px; width: auto; } .form-v2-content .form-detail .form-row input { width: 95%; } .form-v2-content .form-detail .form-checkbox { width: 100%; } } @media screen and (max-width: 575px) { .form-v2-content .form-detail .form-row input { width: 89.5%; } } #field { margin-left: .5em; float: left; } #field, label { float: left; font-family: Arial, Helvetica, sans-serif; font-size: small; } br { clear: both; } input { border: 1px solid black; margin-bottom: .5em; } input.error { border: 1px solid red; } label.error { background: url('images/unchecked.gif') no-repeat; padding-left: 16px; margin-left: .3em; } label.valid { background: url('images/checked.gif') no-repeat; display: block; width: 16px; height: 16px; }Run C:\python_dev\registration>python main.py