2

I am currently learning how to work with the tkinter gui and I am trying to integrate with SQLAlchemy. The first hurdle was figuring out how to move between frames without destroying/closing the window, luckily I found this question: Switch between two frames in tkinter. So I used a lot of the provided code and created a simple application that is trying to have someone log in.

Now for the part I can't figure out. I have a function _check_credentials(self) deep inside the structure of windows that is trying to query the db. I have successfully created the table and queried it elsewhere.

I need to pass the session from the main.py module to the Login class and finally to the _check_credentials(self) method.

main.py -> Authorzation() -> Login() -> login_btn = tk.Button() -> _check_credentials()

Additional info:

I have included all of my code. Right now it runs, but crashes when the login button is pressed. I have attempted to pass the session directly, ie. Authorzation(Session) but that crashes immediately.

Also, I am trying to follow the guidelines laid out in the sqlalchemy docs http://docs.sqlalchemy.org/en/latest/orm/session.html, FAQ, "When do I construct a Session, when do I commit it, and when do I close it?".

main.py:

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker 

from module1 import Authorzation

import Tkinter as tk

Base = declarative_base()
engine = create_engine('sqlite:///:memory:', echo=True)
Base.metadata.create_all(engine)

Session = sessionmaker(bind=engine)
session = Session()


app = Authorzation()
app.mainloop()

module1.py:

import Tkinter as tk
import user

TITLE_FONT = ("Helvetica", 18, "bold")

class Authorzation(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        # the container is where we'll stack a bunch of frames
        # on top of each other, then the one we want visible
        # will be raised above the others
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}
        for F in (Login, Register):
            frame = F(container, self)
            self.frames[F] = frame
            # put all of the pages in the same location; 
            # the one on the top of the stacking order
            # will be the one that is visible.
            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(Login)

    def show_frame(self, c):
        '''Show a frame for the given class'''
        frame = self.frames[c]
        frame.tkraise()

class Login(tk.Frame):
    def __init__(self, parent, controller):
        self.controller = controller

        tk.Frame.__init__(self, parent) 
        label = tk.Label(self, text="Title", font=TITLE_FONT)
        label.pack(side="top", fill="x", pady=10)

        #Create the Username field
        label_username = tk.Label(self, text="username")
        label_username.pack()
        self.username = tk.StringVar()
        tk.Entry(self, textvariable=self.username).pack()

        #Create the password field
        label_password = tk.Label(self, text="password")
        label_password.pack()
        self.password = tk.StringVar()
        tk.Entry(self, textvariable=self.password).pack()


        login_btn = tk.Button(self, text="Login", 
                            command=self._check_credentials)
        login_btn.pack(pady=5)

        reg_btn = tk.Button(self, text="Registration", 
                            command=lambda: controller.show_frame(Register))
        reg_btn.pack(pady=10)

    def _check_credentials(self):
        session_user = session.query(user.User)\
                                    .filter_by(
                                               username=self.username
                                            ).first() 
        if session_user:
            return session_user.check_pwd(), session_user
        else:
            print("Sorry we could not find your username")
            return False, None

        self.controller.show_frame(Login)

class Register(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent) 
        label = tk.Label(self, text="This is page 1", font=TITLE_FONT)
        label.pack(side="top", fill="x", pady=10)
        button = tk.Button(self, text="Go to the start page", 
                           command=lambda: controller.show_frame(Login))
        button.pack()
Community
  • 1
  • 1
pompousPanda
  • 105
  • 2
  • 10

1 Answers1

1

After doing research on *args, and **kwargs. I realized I had not tried putting the session first in the __init__() function. Here is how I then passed the session to the controller.

main.py:

app = Authorzation(session)

module1.py

class Authorzation(tk.Tk):
    def __init__(self, session, *args, **kwargs):
        self.session = session

Once the session was in the controller it was easy to reference it from the Login() frame.

module1.py:

class Login(tk.Frame):
    def __init__(self, parent, controller):
        self.controller = controller

        ...

    def _check_credentials(self):
        session = self.controller.session

Note: this solution is also nice because it alleviates the need to pass the session through the button.

pompousPanda
  • 105
  • 2
  • 10