Python Forum
Current project - Simple tkinter login system
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Current project - Simple tkinter login system
#1
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()
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply


Messages In This Thread
Current project - Simple tkinter login system - by menator01 - Aug-28-2023, 07:21 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  Current Project menator01 3 2,419 Apr-27-2022, 03:35 PM
Last Post: menator01
  Created a simple GUI to get myself started with TkInter! bixitz 4 3,131 Apr-04-2019, 05:33 PM
Last Post: buran

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020