Передача сеанса SQLAlchemy на контроллер TKinter

В настоящее время я изучаю, как работать с tkinter gui, и я пытаюсь интегрироваться с SQLAlchemy. Первое препятствие заключалось в том, как перемещаться между кадрами без разрушения/закрытия окна, к счастью, я нашел этот вопрос: Переключитесь между двумя кадрами в tkinter. Поэтому я использовал много предоставленного кода и создал простое приложение, которое пытается заставить кого-то войти в систему.

Теперь для части я не могу понять. У меня есть функция _check_credentials (self) глубоко внутри структуры окон, которая пытается запросить db. Я успешно создал таблицу и задал ее в другом месте.

Мне нужно передать сеанс из модуля main.py в класс Login и, наконец, в метод _check_credentials (self).

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

Дополнительная информация:

Я включил весь мой код. Сейчас он запускается, но сбой при нажатии кнопки входа в систему. Я попытался передать сессию напрямую, т.е. Authorzation (Session), но это немедленно сработает.

Кроме того, я стараюсь следовать рекомендациям, изложенным в документах sqlalchemy http://docs.sqlalchemy.org/en/latest/orm/session.html, FAQ: "Когда я создаю сеанс, когда я его совершу, и когда я его закрою? ".

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()
1 ответ

После исследования на * args и ** kwargs. Я понял, что не пробовал сначала поставить сессию в функции __init__(). Вот как я передал сессию контроллеру.

main.py:

app = Authorzation(session)

module1.py

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

Когда сессия была в контроллере, было легко ссылаться на нее из фрейма Login().

module1.py:

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

Примечание. Это решение также хорошо, потому что оно облегчает передачу сеанса через кнопку.

licensed under cc by-sa 3.0 with attribution.