Форум сайта python.su
Всё работает. Но явно - это можно сделать как-то проще и правильнее. Подскажите,пожалуйста, как или ткните - где можно почитать. 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_())
Отредактировано yuyu_yaya (Ноя. 1, 2017 19:52:04)
Офлайн
логин лучше делать на основе QDialog
https://github.com/baoboa/pyqt5/tree/master/examples/dialogs
Офлайн
vic57
Спасибо за ссылку. Погляжу - что там. Перепишу через QDialog. Главная сложность для меня - это обработка исключений, а также то, где и как правильно создать и проверить соединение - то ли сразу в главном окне, то ли в диалоговом, а потом передать его в конструктор главного окна.
Отредактировано yuyu_yaya (Ноя. 1, 2017 19:49:34)
Офлайн
там же на гите есть sql примеры.
я работаю по схеме: подключился->запрос-ответ->отключился
Офлайн
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_())
Отредактировано yuyu_yaya (Ноя. 2, 2017 14:01:29)
Офлайн
ну можно и так, но я бы сначала в консоле все отработал, потом бы в гуй запихал
и всю работу с БД я выделяю в отдельный класс типа connection(host,user….blabla)
Отредактировано vic57 (Ноя. 2, 2017 15:42:07)
Офлайн
Я на тестовой базе Oracle, которая на виртуалке крутится, всё это делаю. Мне интересно собрать всё воедино и посмотреть как получится. Потом,конечно, когда буду переносить всё на реальную базу - все запросы, функции, процедуры буду сначала тщательно тестировать в консоли. И только потом в гуй переносить.
Update: Я думал насчёт отдельного класса для БД. Только так для себя не понял, какую от этого выгоду можно получить!?
Отредактировано yuyu_yaya (Ноя. 2, 2017 19:00:38)
Офлайн
yuyu_yayaможно отработать в консоли и пользовать где угодно, так же как и диалог соединения
Update: Я думал на счёт отдельного класса для БД. Только так для себя не понял, какую от этого выгоду можно получить!?
Офлайн
yuyu_yayaможно отработать в консоли и пользовать где угодно, так же как и диалог соединения
Update: Я думал на счёт отдельного класса для БД. Только так для себя не понял, какую от этого выгоду можно получить!?
Офлайн
yuyu_yayaможно отработать в консоли и пользовать где угодно, так же как и диалог соединения
Update: Я думал на счёт отдельного класса для БД. Только так для себя не понял, какую от этого выгоду можно получить!?
Офлайн