Найти - Пользователи
Полная версия: Как правильно реализовать логин-форму на PyQt5 + cx_Oracle?
Начало » Базы данных » Как правильно реализовать логин-форму на PyQt5 + cx_Oracle?
1 2
yuyu_yaya
Всё работает. Но явно - это можно сделать как-то проще и правильнее. Подскажите,пожалуйста, как или ткните - где можно почитать. Upd: И насколько правильно так закрывать соединение с базой? Можно ли это делать в деструкторе объекта?
from PyQt5 import QtWidgets,QtCore
import cx_Oracle

class LoginWindow(QtWidgets.QWidget):

connect_db = QtCore.pyqtSignal()
def __init__(self,parent=None):
super().__init__(parent)
self.setUi()

def setUi(self):
self.setWindowFlags(QtCore.Qt.WindowCloseButtonHint)
self.setFixedSize(400,200)
vbox = QtWidgets.QVBoxLayout()
self.button = QtWidgets.QPushButton("&Отправить")
self.lineEditUser = QtWidgets.QLineEdit()
self.lineEditPassword = QtWidgets.QLineEdit()
self.lineEditPassword.setEchoMode(QtWidgets.QLineEdit.Password)
self.lineEditDB = QtWidgets.QLineEdit()
groupBox = QtWidgets.QGroupBox()
form = QtWidgets.QFormLayout()
form.addRow("&Имя пользователя: ", self.lineEditUser)
form.addRow("&Пароль: ", self.lineEditPassword)
form.addRow("&База данных: ", self.lineEditDB)
groupBox.setLayout(form)
vbox.addWidget(groupBox)
vbox.addWidget(self.button)
self.setLayout(vbox)
self.button.clicked.connect(self.on_clicked)

@QtCore.pyqtSlot()
def on_clicked(self):
try:
self.setCursor(QtCore.Qt.WaitCursor)
w.connect_db(self.lineEditUser.text(),self.lineEditPassword.text(),self.lineEditDB.text())
self.unsetCursor()
self.close()
self.connect_db.emit()
except cx_Oracle.DatabaseError as e:
self.show_message("Ошибка подключения к базе данных", "Ошибка базы данных: %s" % e)
self.unsetCursor()

def show_message(self,title,message):
QtWidgets.QMessageBox.about(self,title,message)

class MainWindow (QtWidgets.QMainWindow):
def __init__(self,parent=None):
super().__init__(parent)
self.resize(800,600)

def __del__(self):
self.disconnect_db()

def connect_db(self,user,password,db):
try:
self.con = cx_Oracle.connect(user,password,db)
except cx_Oracle.DatabaseError as e:
raise
else:
self.cursor = self.con.cursor()

def disconnect_db(self):
try:
self.cursor.close()
self.con.close()
except AttributeError:
pass


if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
l = LoginWindow()
w = MainWindow()
l.connect_db.connect(w.show)
l.show()
sys.exit(app.exec_())
vic57
логин лучше делать на основе QDialog
https://github.com/baoboa/pyqt5/tree/master/examples/dialogs
yuyu_yaya
vic57
Спасибо за ссылку. Погляжу - что там. Перепишу через QDialog. Главная сложность для меня - это обработка исключений, а также то, где и как правильно создать и проверить соединение - то ли сразу в главном окне, то ли в диалоговом, а потом передать его в конструктор главного окна.
vic57
там же на гите есть sql примеры.
я работаю по схеме: подключился->запрос-ответ->отключился
yuyu_yaya
vic57
Пока примеры на git не привели меня к пониманию. По sql там какой-то совсем простой код. Попробовал переписать c использованием QDialog и по схеме постоянного открытия/закрытия соединения для каждой операции. Как-то так получилось:
 from PyQt5 import QtWidgets,QtCore
import cx_Oracle
# from mainwindow import Ui_MainWindow
class Login(QtWidgets.QDialog):
    def __init__(self,parent=None):
        super().__init__(parent)
        self.setUi()
    def setUi(self):
        self.setWindowFlags(QtCore.Qt.WindowCloseButtonHint)
        self.setFixedSize(400,200)
        vbox = QtWidgets.QVBoxLayout()
        self.button = QtWidgets.QPushButton("&Отправить")
        self.lineEditUser = QtWidgets.QLineEdit()
        self.lineEditPassword = QtWidgets.QLineEdit()
        self.lineEditPassword.setEchoMode(QtWidgets.QLineEdit.Password)
        self.lineEditDB = QtWidgets.QLineEdit()
        groupBox = QtWidgets.QGroupBox()
        form = QtWidgets.QFormLayout()
        form.addRow("&Имя пользователя: ", self.lineEditUser)
        form.addRow("&Пароль: ", self.lineEditPassword)
        form.addRow("&База данных: ", self.lineEditDB)
        groupBox.setLayout(form)
        vbox.addWidget(groupBox)
        vbox.addWidget(self.button)
        self.setLayout(vbox)
        self.button.clicked.connect(self.on_clicked)
# Насколько правильно использовать менеджер контекста? Вроде бы  курсоры и соединения так закрываются автоматически.
    def on_clicked(self):
        self.user = self.lineEditUser.text()
        self.password = self.lineEditPassword.text()
        self.dns = self.lineEditDB.text()
        try:
            with cx_Oracle.connect(self.user,self.password,self.dns) as con:
                pass
            self.accept()
        except cx_Oracle.DatabaseError as e:
            self.show_message("Ошибка подключения к базе данных", "Ошибка базы данных: %s" % e)
    def show_message(self, title, message):
        QtWidgets.QMessageBox.warning(self, title, message)
class Window(QtWidgets.QMainWindow):
    def __init__(self, parent=None,user="",password="",dns=""):
        super().__init__(parent)
        self._user = user
        self._password = password
        self._dns = dns
        self.show_banner("select banner from v$version")
        # self.ui = Ui_MainWindow()
        # self.ui.setupUi(self)
# Правильно ли открывать соединения так каждый раз? Или существует какой-то другой способ получше?
    def show_banner (self,sql):
        try:
            with cx_Oracle.connect(self._user,self._password,self._dns) as con:
                cursor = con.cursor()
                cursor.execute(sql)
                for row in cursor:
                    print(row[0])
        except cx_Oracle.DatabaseError as e:
            self.show_message("Ошибка подключения к базе данных", "Ошибка базы данных: %s" % e)
    def show_message(self, title, message):
        QtWidgets.QMessageBox.warning(self, title, message)
if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    login = Login()
# Правильно ли так передавать учётные данные в главное окно?
    if login.exec_() == QtWidgets.QDialog.Accepted:
        window = Window(user=login.user, password=login.password, dns=login.dns)
        window.show()
        sys.exit(app.exec_())
Так лучше?
vic57
ну можно и так, но я бы сначала в консоле все отработал, потом бы в гуй запихал
и всю работу с БД я выделяю в отдельный класс типа connection(host,user….blabla)
yuyu_yaya
Я на тестовой базе Oracle, которая на виртуалке крутится, всё это делаю. Мне интересно собрать всё воедино и посмотреть как получится. Потом,конечно, когда буду переносить всё на реальную базу - все запросы, функции, процедуры буду сначала тщательно тестировать в консоли. И только потом в гуй переносить.
Update: Я думал насчёт отдельного класса для БД. Только так для себя не понял, какую от этого выгоду можно получить!?
vic57
yuyu_yaya
Update: Я думал на счёт отдельного класса для БД. Только так для себя не понял, какую от этого выгоду можно получить!?
можно отработать в консоли и пользовать где угодно, так же как и диалог соединения
у вас как-то все вперемешку, не видно модульной структуры
правило UNIX - делай одно, но делай хорошо
vic57
yuyu_yaya
Update: Я думал на счёт отдельного класса для БД. Только так для себя не понял, какую от этого выгоду можно получить!?
можно отработать в консоли и пользовать где угодно, так же как и диалог соединения
у вас как-то все вперемешку, не видно модульной структуры
правило UNIX - делай одно, но делай хорошо
vic57
yuyu_yaya
Update: Я думал на счёт отдельного класса для БД. Только так для себя не понял, какую от этого выгоду можно получить!?
можно отработать в консоли и пользовать где угодно, так же как и диалог соединения
у вас как-то все вперемешку, не видно модульной структуры
правило UNIX - делай одно, но делай хорошо
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB