menator01
Silver Coder
Doesn't really do anything. Register a user, login a user, logout a user. displays a message for logged in users.
Python:
import tkinter as tk
import sqlite3 as sq
import os
import webbrowser
from urllib.request import urlopen
# Executed from bash shell or vscode - vscode is 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 register(self, name, email, password):
''' Method add data to the database and handles some error checking '''
query = '''
insert into customer (name, email, password) values (?,?,?)
'''
self.cursor.execute(query, (name.lower().strip(), email.lower().strip(), password))
self.db.commit()
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:
return True
return False
class Window:
'''
Window class is the main display window
'''
def __init__(self, parent):
self.parent = parent
self.parent.minsize(800,600)
parent.title('Main Page')
parent.columnconfigure(0, weight=1)
parent.rowconfigure(0, weight=1)
# Container frame for holding all widgets
container = tk.Frame(parent, bg='#555555')
container.grid(column=0, row=0, sticky='news', padx=5, pady=5)
container.grid_columnconfigure(0, weight=3)
container.grid_rowconfigure(2, weight=3)
# Link container to hold various link frames
linksframe = tk.Frame(container, bg='white')
linksframe.grid(column=0, row=1, sticky='new')
linksframe.grid_columnconfigure(0, weight=0)
linksframe.grid_columnconfigure(1, weight=3)
linksframe.grid_columnconfigure(2, weight=3)
links = tk.Frame(linksframe, bg='white')
links.grid(column=0, row=0, sticky='new')
# Admin container will show when logged in
self.adminframe =tk.Frame(linksframe, bg='white')
self.adminframe.grid(column=1, row=0, sticky='new')
self.adminframe.grid_columnconfigure(0, weight=3)
# Footer Frame
footerframe = tk.Frame(container, bg='#333333')
footerframe.grid(column=0, row=2, sticky='sew')
footerframe.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)
# Create our links using labels. Bind links to give a hover effect
self.login_label = tk.Label(links, 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(links, 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(links, 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(linksframe, text='Exit', fg='orangered', bg='white', cursor='hand2')
self.exit_label['font'] = (None, 12, 'normal')
self.exit_label.grid(column=2, row=0, padx=(5,10), pady=5, sticky='e')
self.exit_label.bind('<Enter>', self.exit_enter)
self.exit_label.bind('<Leave>', self.exit_leave)
# The user/admin frame is hidden until logged in
adminlabel = tk.Label(self.adminframe, text='Admin stuff here', bg='white')
adminlabel['font'] = (None, 12, 'normal')
adminlabel.grid(column=0, row=0, padx=5, pady=5, sticky='new')
self.footer = tk.Label(footerframe, text='my-python.org')
self.footer['bg'] = '#333333'
self.footer['fg'] = '#cecece'
self.footer['font'] = ('cursive', 14, 'normal')
self.footer['cursor'] = 'hand2'
self.footer.grid(column=0, row=2, ipady=5)
self.footer.bind('<Enter>', lambda event: self.footer_on(self.footer))
self.footer.bind('<Leave>', lambda event: self.footer_off(self.footer))
# 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'
def footer_on(self, label):
label['fg'] = '#ffffff'
def footer_off(self, label):
label['fg'] = '#cecece'
class LoginForm:
def __init__(self, parent):
self.parent = parent
self.window = tk.Toplevel(None)
self.window.title('Login Form')
self.window.minsize(800,200)
self.window.columnconfigure(0, weight=1)
self.window.rowconfigure(0, weight=1)
container = tk.Frame(self.window, bg='#555555')
container.grid(column=0, row=0, sticky='new', padx=5, pady=5)
container.grid_columnconfigure(0, weight=3)
formframe = tk.Frame(container, bg='#555555')
formframe.grid(column=0, row=1, sticky='new', pady=10)
btnframe = tk.Frame(container, bg='#555555')
btnframe.grid(column=0, row=2, sticky='new', pady=5)
# 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)
# Create the form headers and fields
label = tk.Label(formframe, text='Email:', bg='#555555', fg='white', anchor='w')
label['font'] = (None, 12, 'bold')
label.grid(column=0, row=0, sticky='new', pady=4, padx=2)
label = tk.Label(formframe, text='Password:', bg='#555555', fg='white', anchor='w')
label['font'] = (None, 12, 'bold')
label.grid(column=0, row=1, sticky='new', pady=4, padx=2)
self.user = tk.Entry(formframe, font=(None, 12, 'normal'))
self.user.focus()
self.user.grid(column=1, row=0, sticky='new', pady=4, padx=2)
self.passwd = tk.Entry(formframe, font=(None, 12, 'normal'))
self.passwd.grid(column=1, row=1, sticky='new', pady=4, padx=2)
# Create the buttons
self.loginbtn = tk.Button(btnframe, text='Login', bg='#BCD4E6', fg='black')
self.loginbtn['activebackground'] = '#6CA0DC'
self.loginbtn['activeforeground'] = 'white'
self.loginbtn['font'] = (None, 12, 'normal')
self.loginbtn['cursor'] = 'hand2'
self.loginbtn['highlightbackground'] = 'black'
self.loginbtn['highlightcolor'] = 'black'
self.loginbtn.grid(column=0, row=0, sticky='new', padx=5, pady=5)
self.cancelbtn = tk.Button(btnframe, text='Cancel', bg='tomato', fg='black')
self.cancelbtn['font'] = (None, 12, 'normal')
self.cancelbtn['activebackground'] = 'orangered'
self.cancelbtn['activeforeground'] = 'white'
self.cancelbtn['cursor'] = 'hand2'
self.cancelbtn['highlightbackground'] = 'black'
self.cancelbtn['highlightcolor'] = 'black'
self.cancelbtn.grid(column=1, row=0, sticky='new', padx=5, pady=5)
self.msg = tk.Label(container, bg='#555555', fg='white', font=(None, 12, 'bold'))
self.msg.grid(column=0, row=3, sticky='new')
class RegisterForm:
def __init__(self, parent):
self.parent = parent
self.window = tk.Toplevel(None)
self.window.title('Registration Form')
self.window.minsize(800,250)
self.window.columnconfigure(0, weight=1)
self.window.rowconfigure(0, weight=1)
container = tk.Frame(self.window, bg='#555555')
container.grid(column=0, row=0, sticky='new', padx=5, pady=5)
container.grid_columnconfigure(0, weight=3)
formframe = tk.Frame(container, bg='#555555')
formframe.grid(column=0, row=1, sticky='new', pady=10)
btnframe = tk.Frame(container, bg='#555555')
btnframe.grid(column=0, row=2, sticky='new', pady=5)
# 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)
# Create Field Headers
label = tk.Label(formframe, text='Name:', bg='#555555', fg='white', anchor='w', pady=5, font=(None, 12, 'bold'))
label.grid(column=0, row=0, sticky='new', pady=5)
label = tk.Label(formframe, text='Email:', bg='#555555', fg='white', anchor='w', pady=5, font=(None, 12, 'bold'))
label.grid(column=0, row=1, sticky='new', pady=5)
label = tk.Label(formframe, text='Password:', bg='#555555', fg='white', anchor='w', pady=5, font=(None, 12, 'bold'))
label.grid(column=0, row=2, sticky='new', pady=5)
#Create Fields
self.name = tk.Entry(formframe, font=(None, 12, 'normal'))
self.name.grid(column=1, row=0, sticky='new', pady=5, padx=5)
self.email = tk.Entry(formframe, font=(None, 12, 'normal'))
self.email.grid(column=1, row=1, sticky='new', pady=5, padx=5)
self.password = tk.Entry(formframe, font=(None, 12, 'normal'))
self.password.grid(column=1, row=2, sticky='new', pady=5, padx=5)
# Create the buttons
self.registerbtn = tk.Button(btnframe, text='Register', bg='#BCD4E6', fg='black')
self.registerbtn['activebackground'] = '#6CA0DC'
self.registerbtn['activeforeground'] = 'white'
self.registerbtn['font'] = (None, 12, 'normal')
self.registerbtn['cursor'] = 'hand2'
self.registerbtn['highlightbackground'] = 'black'
self.registerbtn['highlightcolor'] = 'black'
self.registerbtn.grid(column=0, row=0, sticky='new', padx=5, pady=5)
self.cancelbtn = tk.Button(btnframe, text='Cancel', bg='tomato', fg='black')
self.cancelbtn['font'] = (None, 12, 'normal')
self.cancelbtn['activebackground'] = 'orangered'
self.cancelbtn['activeforeground'] = 'white'
self.cancelbtn['cursor'] = 'hand2'
self.cancelbtn['highlightbackground'] = 'black'
self.cancelbtn['highlightcolor'] = 'black'
self.cancelbtn.grid(column=1, row=0, sticky='new', padx=5, pady=5)
self.msg = tk.Label(container, font=(None, 14, 'bold'), fg='white')
self.msg.grid(column=0, row=3, sticky='new')
class Controller:
'''
Controll class handles all communication between the classes
'''
def __init__(self, database, window, loginform, registerform):
# Set some class variables
self.database = database
self.window = window
self.loginform = loginform
self.registerform = registerform
self.id = None
# This hides the user/admin frame upon script start
self.window.adminframe.grid_remove()
# Withdraw login and register forms
self.loginform.window.withdraw()
self.registerform.window.withdraw()
# Window Link Commands
self.window.login_label.bind('<Button-1>', self.loginpage)
self.window.logout_label.bind('<Button-1>', self.logout)
self.window.register_label.bind('<Button-1>', self.registerpage)
self.window.exit_label.bind('<Button-1>', self.terminate)
self.loginform.window.protocol('WM_DELETE_WINDOW', lambda: self.close(self.loginform.window))
self.registerform.window.protocol('WM_DELETE_WINDOW', lambda: self.close(self.registerform.window))
self.window.footer.bind('<Button-1>', self.link)
# Button Commands
self.loginform.cancelbtn['command'] = lambda: self.close(self.loginform.window)
self.loginform.loginbtn['command'] = self.login
self.registerform.registerbtn['command'] = self.register
self.registerform.cancelbtn['command'] = lambda: self.close(self.registerform.window)
def link(self, event):
webbrowser.open('http://my-python.org')
def loginpage(self, event):
''' Pulls up the login form and withdraws the main window '''
self.loginform.msg['text'] = ''
self.loginform.user.delete(0, 'end')
self.loginform.passwd.delete(0, 'end')
self.window.parent.withdraw()
self.loginform.window.deiconify()
def login(self):
'''
Method for getting the email and password from the loginform class form.
Checks if the fields are empty, and if the user and email are in the database.
Displays the appropiate message if error. If all is good, withdraws the login form,
clears the fields and returns to the main window showing the user/admin content.
'''
user, password = self.loginform.user.get(), self.loginform.passwd.get()
self.update()
if user.lower().strip() == '' or password.strip() == '':
self.loginform.msg['text'] = 'Either email or password is empty.'
self.loginform.msg['bg'] = '#333333'
elif not self.database.login(user, password):
self.loginform.user.focus()
self.loginform.msg['text'] = 'Either email or password is incorrect. Please try again.'
self.loginform.msg['bg'] = '#333333'
else:
self.window.adminframe.grid()
self.update()
self.close(self.loginform.window)
def update(self):
''' Method resets all the form msg text and clears fields. '''
self.loginform.msg['text'] = ''
self.loginform.msg['bg'] = '#555555'
self.loginform.user.delete(0, 'end')
self.loginform.passwd.delete(0, 'end')
self.registerform.msg['text'] = ''
self.registerform.msg['bg'] = '#555555'
self.registerform.name.delete(0, 'end')
self.registerform.email.delete(0, 'end')
self.registerform.password.delete(0, 'end')
def logout(self, event):
''' Logs out the user and hides the user/admin frame '''
self.window.adminframe.grid_remove()
def registerpage(self, event):
''' Method withdraws main window and pulls up regustration form '''
self.window.parent.withdraw()
self.registerform.window.deiconify()
self.registerform.msg['bg'] = '#555555'
self.registerform.msg['text'] = ''
def register(self):
''' Method gets values from the register form and checks if all fields are entered
and does a simple check of email format
'''
name, email, password = self.registerform.name.get(), self.registerform.email.get(), self.registerform.password.get()
if name == '' or email == '' or password == '':
self.registerform.msg['text'] = 'All fields are required'
self.registerform.msg['bg'] = '#333333'
else:
try:
self.database.register(name, email, password)
except sq.IntegrityError as error:
if 'constraint' in str(error) and 'customer.email' in str(error):
self.registerform.msg['text'] = 'That email already exist in the database.'
self.registerform.msg['bg'] = '#333333'
self.registerform.email.delete(0, 'end')
elif 'CHECK' in str(error):
self.registerform.msg['text'] = 'That is not a valid email.'
self.registerform.msg['bg'] = '#333333'
self.registerform.email.delete(0, 'end')
else:
self.registerform.msg['text'] = 'An unkwon error has occurred'
self.registerform.msg['bg'] = '#333333'
else:
self.registerform.name.delete(0, 'end')
self.registerform.email.delete(0, 'end')
self.registerform.password.delete(0, 'end')
self.registerform.window.withdraw()
self.loginform.window.deiconify()
def terminate(self,event):
''' Method destroys root window and ends script. '''
self.window.parent.destroy()
def close(self, window):
''' Method is used to withdraw various toplevel windows and returns the main window. '''
window.withdraw()
self.update()
self.window.parent.deiconify()
if __name__ == '__main__':
root = tk.Tk()
root['pady'] = 5
root['padx'] = 5
img = urlopen('https://my-python.org/images/code-forum/light/light_on.png')
data = img.read()
image = tk.PhotoImage(data=data)
root.wm_iconphoto(True, image)
controller = Controller(Database(), Window(root), LoginForm(root), RegisterForm(root))
controller.database.create()
root.mainloop()
Last edited: