Aug-28-2023, 07:21 PM
Just a simple login system. It's not complete, still have some details to work on and after maybe make a generic page class as I have some repeating code.
# Do the imports import tkinter as tk from tkinter import font import sqlite3 as sq import os # Executed from bash shell or vscode - vscode default path = os.path.dirname(os.sys.argv[0]) if not path: path = '.' class Database: ''' Database class handles all methods for the adding, deleting, and retrieving information ''' def __init__(self): ''' Setup the sqlite3 database and cursor ''' self.db = sq.connect(f'{path}/customer.db') self.cursor = self.db.cursor() def create(self): ''' create creates the table and sets up a basic email validation ''' query = ''' create table if not exists customer ( id integer primary key, name text not null, email text unique not null, password text not null, logged_in integer not null default 0 check( email like '%_@_%._%' and length(email) - length(replace(email, '@', '')) = 1 and substr(lower(email), 1, instr(email, '.') - 1) not glob '*[^@0-9a-z]*' and substr(lower(email), instr(email, '.') + 1) not glob '*[^a-z]*' )) ''' # Execute and commit the query self.db.execute(query) self.db.commit() def add(self, name, email, password): ''' Method add data to the database and handles some error checking ''' query = ''' insert into customer (name, email, password) values (?,?,?) ''' try: self.cursor.execute(query, (name.lower().strip(), email.lower().strip(), password)) self.db.commit() return ' Added user to database.' except sq.OperationalError as error: return error except sq.IntegrityError as error: if 'constraint' in str(error) and 'customer.email' in str(error): return 'That email already exists. Please try again.' elif 'CHECK' in str(error): return 'That is not a valid email. Please try again.' else: return 'An unknown error has occurred' def remove(self, id): ''' Method for removing users by id ''' if id: self.cursor.execute(f'delete from customer where id = {id}') def getall(self): ''' Method gets all information from database ''' return self.cursor.execute('select * from customer').fetchall() def getone(self, id): ''' Method gets information for a single id ''' if id: return self.cursor.execute(f'select * from customer where id = {id}').fetchone() def login(self, email, password): ''' Method checks if a user is in the database based on email and password if a user is found then it will set a session variable for being logged in. ''' query = f''' select id, email, password from customer where email = "{email}" and password = "{password}" ''' res = self.cursor.execute(query).fetchone() if res: self.update(res[0], 1) return True return False def update(self, id, log=int(0)): ''' Helper method for above method. Set the logged_in field to 1 ''' self.cursor.execute(f'update customer set logged_in = {log} where id = {id}') def logout(self, id, log=int(0)): ''' Method for logging out. Sets the logged_in field to 0 ''' self.cursor.execute(f'update customer set logged_in = {log} where id = {id}') class Window: ''' Window class is the main display window ''' def __init__(self, parent): self.parent = parent parent.title('Main Page') parent.columnconfigure(0, weight=1) parent.rowconfigure(0, weight=1) parent.update() width = parent.winfo_reqwidth() * 3 # Container frame for holding all widgets container = tk.Frame(parent, bg='#555555') container.grid(column=0, row=0, sticky='news') container.grid_columnconfigure(0, weight=3) # Simple header label header = tk.Label(container, text='Main Page') header['font'] = ('cursive', 30, 'bold') header['bg'] = '#333333' header['fg'] = 'whitesmoke' header['relief'] = 'solid' header['borderwidth'] = 1 header.grid(column=0, row=0, sticky='new', ipady=10) # The container holds all our links link_container = tk.Frame(container, bg='white') link_container.grid(column=0, row=1, sticky='new') # Create our links using labels. Bind links to give a hover effect self.login_label = tk.Label(link_container, text='Login', fg='blue', bg='white', cursor='hand2') self.login_label['font'] = (None, 12, 'normal') self.login_label.grid(column=0, row=0, padx=5, pady=5) self.login_label.bind('<Enter>', lambda label: self.link_on(self.login_label)) self.login_label.bind('<Leave>', lambda label: self.link_off(self.login_label)) self.logout_label = tk.Label(link_container, text='Logout', fg='blue', bg='white', cursor='hand2') self.logout_label['font'] = (None, 12, 'normal') self.logout_label.grid(column=1, row=0, padx=5, pady=5) self.logout_label.bind('<Enter>', lambda label: self.link_on(self.logout_label)) self.logout_label.bind('<Leave>', lambda label: self.link_off(self.logout_label)) self.register_label = tk.Label(link_container, text='Register', fg='blue', bg='white', cursor='hand2') self.register_label['font'] = (None, 12, 'normal') self.register_label.grid(column=2, row=0, padx=5, pady=5) self.register_label.bind('<Enter>', lambda label: self.link_on(self.register_label)) self.register_label.bind('<Leave>', lambda label: self.link_off(self.register_label)) self.exit_label = tk.Label(link_container, text='Exit', fg='tomato', bg='white', cursor='hand2') self.exit_label['font'] = (None, 14, 'normal') self.exit_label.grid(column=3, row=0, padx=(width,10), pady=5) self.exit_label.bind('<Enter>', self.exit_enter) self.exit_label.bind('<Leave>', self.exit_leave) self.log = tk.Label(container, text='Your are logged out', bg='#555555', fg='#cecece', anchor='e', padx=5) self.log['font'] = (None, 12, 'bold') self.log.grid(column=0, row=2, padx=5, pady=5, sticky='new') # These methods provide the hover effects def link_on(self, label): label['fg'] = 'orangered' def link_off(self, label): label['fg'] = 'blue' def exit_enter(self, event): self.exit_label['fg'] = 'red' def exit_leave(self, event): self.exit_label['fg'] = 'tomato' class LoginForm: ''' This class contains our login form''' def __init__(self, parent): self.parent = parent def form(self): self.window = tk.Toplevel(None) self.window.minsize(800,600) self.window['padx'] = 3 self.window['pady'] = 3 self.window.title('A Login Form') self.window.columnconfigure(0, weight=1) self.window.rowconfigure(0, weight=1) self.window['bg'] = '#333333' container = tk.Label(self.window, bg='#555555') container.grid(column=0, row=0, sticky='news') container.grid_columnconfigure(0, weight=3) # Simple header label header = tk.Label(container, text='Login Page') header['font'] = ('cursive', 30, 'bold') header['bg'] = '#333333' header['fg'] = 'whitesmoke' header['relief'] = 'solid' header['borderwidth'] = 1 header.grid(column=0, row=0, sticky='new', ipady=10) self.button = tk.Button(self.window, text='Cancel', bg='tomato', fg='black', cursor='hand2') self.button['font'] = (None, 12, 'normal') self.button['command'] = self.close self.button['highlightbackground'] = 'black' self.button['highlightcolor'] = 'black' self.button.grid(column=0, row=1) self.button.bind('<Enter>', self.on_enter) def close(self): ''' Method for destroying the form window and retreiving the main window ''' self.window.destroy() self.parent.deiconify() def on_enter(self, event): # method for hover effect of the cancel button self.button['activebackground'] = 'orangered' self.button['activeforeground'] = 'white' class RegisterForm: ''' This class contains the registraion form ''' def __init__(self, parent): self.parent = parent def form(self): self.window = tk.Toplevel(None) self.window.minsize(800,600) self.window['padx'] = 3 self.window['pady'] = 3 self.window.title('Registation Form') self.window.columnconfigure(0, weight=1) self.window.rowconfigure(0, weight=1) self.window['bg'] = '#333333' container = tk.Label(self.window, bg='#555555') container.grid(column=0, row=0, sticky='news') container.grid_columnconfigure(0, weight=3) # Simple header label header = tk.Label(container, text='Registration Page') header['font'] = ('cursive', 30, 'bold') header['bg'] = '#333333' header['fg'] = 'whitesmoke' header['relief'] = 'solid' header['borderwidth'] = 1 header.grid(column=0, row=0, sticky='new', ipady=10) self.button = tk.Button(self.window, text='Cancel', bg='tomato', fg='black', cursor='hand2') self.button['font'] = (None, 12, 'normal') self.button['command'] = self.close self.button['highlightbackground'] = 'black' self.button['highlightcolor'] = 'black' self.button.grid(column=0, row=1) self.button.bind('<Enter>', self.on_enter) def close(self): ''' Method for destroying the form window and retreiving the main window ''' self.window.destroy() self.parent.deiconify() def on_enter(self, event): # method for hover effect of the cancel button self.button['activebackground'] = 'orangered' self.button['activeforeground'] = 'white' def update(self): pass class Controller: ''' Controller class will handle all communications between the other classes ''' def __init__(self, db, window, loginform, registerform): # setup some class variables self.db = db self.window = window self.loginform = loginform self.registerform = registerform self.session = 0 # Window Link Commands self.window.login_label.bind('<Button-1>', lambda event: self.login()) self.window.logout_label.bind('<Button-1>', lambda event: self.logout()) self.window.register_label.bind('<Button-1>', lambda event: self.register()) self.window.exit_label.bind('<Button-1>', lambda event: self.window_exit()) def login(self): ''' Method for getting the login form ''' self.window.parent.withdraw() self.loginform.form() self.window.log['text'] = 'Your logged in' self.window.log['fg'] = 'whitesmoke' def logout(self): ''' Method for logging out ''' self.db.logout(1) self.window.log['text'] = 'Your logged out' self.window.log['fg'] = '#cecece' def register(self): ''' Method for registering new user ''' self.window.parent.withdraw() self.registerform.form() def window_exit(self): ''' Method will log out user and exit program ''' self.db.logout(1) self.window.parent.destroy() if __name__ == '__main__': root = tk.Tk() root.minsize(800, 600) root['padx'] = 3 root['pady'] = 3 controller = Controller(Database(), Window(root), LoginForm(root), RegisterForm(root)) root.mainloop()